2013-06-13 105 views
1

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

流动是一个简化的代码,它显示了问题。

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> 

回答

1

的问题UI线程,我用调度来解决这个PROBL EM

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> 
0

你实际上并没有设置所选客户名称的价值在你的二传手,和你的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"); 
     } 
    } 
+0

这正如我在问题中提到,当客户还没有准备好它不应该在这个例子中,当用户选择“C2”从组合框中setter方法设置所选客户必须后面进行设置,例如是故意的到“C1”(在这个例子中,只有“C1”已准备就绪,这是为了使代码更容易阅读),但是当我运行应用程序时,即使setter选择了“C1”并且getter返回它,但Combobox显示了“ C2“作为选择的项目。 –