2013-06-13 181 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「作爲選擇的項目。 –