1

应用程序中有一个ComboBox绑定到项目集合的应用程序。在某些情况下,用户可以从中选择一个项目,ComboBox但所选项目可能尚未准备好,因此ComboBox所选项目必须返回到前一个所选项目(或集合中的某个其他项目),但在当前应用程序中ComboBox始终显示从用户中选择的项目,而不是在设置它并调用通知属性更改后检索有效项目。

流动是显示问题的简化代码。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private List<Customer> _Customers = new List<Customer>();

    public List<string> CustomerNames
    {
        get
        {
            var list = new List<string>();
            foreach (var c in _Customers)
            {
                list.Add(c.Name);
            }
            return list; ;
        }
    }

    public string CustomerName
    {
        get
        {
            var customer = _Customers.Where(c => c.IsReady).FirstOrDefault();
            return customer.Name;
        }
        set
        {
            NotifyPropertyChanged("CustomerName");
        }
    }

    public MainWindow()
    {
        SetupCustomers();
        InitializeComponent();
        this.DataContext = this;
    }

    private void SetupCustomers()
    {
        _Customers.Add(new Customer("c1", true));
        _Customers.Add(new Customer("c2", false));
        _Customers.Add(new Customer("c3", false));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Customer
{
    public Customer(string name, bool isReady)
    {
        this.Name = name;
        this.IsReady = isReady;
    }

    public bool IsReady { get; set; }

    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }
    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}    


<Window x:Class="TryComboboxReset.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>

    <ComboBox   Width="100"
                Height="25"
                ItemsSource="{Binding Path=CustomerNames, Mode=OneWay}"
                SelectedItem="{Binding Path=CustomerName, Mode=TwoWay}"/>

</Grid>

4

2 回答 2

1

问题是 UI 线程,我使用调度程序来解决这个问题

 public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Customer> _Customers =
        new ObservableCollection<Customer>();

    public ObservableCollection<Customer> CustomerNames
    {
        get
        {
            return _Customers;
        }
    }

    public Customer CustomerName
    {
        get
        {
            return _Customers.Where(c => c.IsReady == true).FirstOrDefault();
        }
        set
        {
            // Delay the revert
            Application.Current.Dispatcher.BeginInvoke(
                new Action(() => NotifyPropertyChanged("CustomerName")), DispatcherPriority.ContextIdle, null);
        }
    }

    public MainWindow()
    {
        SetupCustomers();
        InitializeComponent();
        this.DataContext = this;
    }

    private void SetupCustomers()
    {
        _Customers.Add(new Customer("c1", true));
        _Customers.Add(new Customer("c2", false));
        _Customers.Add(new Customer("c3", false));
        CustomerName = _Customers.Where(c => c.IsReady == true).FirstOrDefault();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Customer
{
    public Customer(string name, bool isReady)
    {
        this.Name = name;
        this.IsReady = isReady;
    }

    public bool IsReady { get; set; }

    public string Name { get; set; }
}   

<ComboBox   Width="400"
            Height="25"
            ItemsSource="{Binding Path=CustomerNames}"
            SelectedValue="{Binding CustomerName,Mode=TwoWay}"    >
       <ComboBox.ItemTemplate>
             <DataTemplate>
                 <TextBlock Text="{Binding Name}"/>
             </DataTemplate>
        </ComboBox.ItemTemplate>
 </ComboBox>
于 2013-06-14T16:32:04.103 回答
0

您实际上并没有在您的 setter 中设置所选客户名称的值,并且您的 getter 总是会返回它找到的第一个“就绪”客户名称......

如果我正确理解了这个问题,你需要做更多的事情:

private string _customerName = null;

public string CustomerName
    {
        get
        {
            if(_customerName == null) 
            {
                _customerName = _Customers.Where(c => c.IsReady).FirstOrDefault().Name;
            }
            return _customerName;
        }
        set
        {
            _customerName = value;
            NotifyPropertyChanged("CustomerName");
        }
    }
于 2013-06-13T01:56:53.377 回答