2013-06-13 8 views
1

В приложении есть приложение ComboBox, которое привязано к коллекции предметов. Есть случаи, когда пользователь может выбрать элемент из , но выбранный элемент может быть еще не готов, поэтому выбранный элемент ComboBox должен вернуться к предыдущему выбранному элементу (или другому элементу в коллекции), но в текущем приложении ComboBox всегда отображает выбранный элемент у пользователя вместо того, чтобы возвращать действительный элемент после его установки и вызова уведомления об изменении свойства.SelectedItem on 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> 

ответ

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

Вы фактически не устанавливая значение выбранного имени клиента в вашем инкубаторе, и ваш добытчик всегда будет возвращать первый «готовое» имя клиента он находит ...

Если я правильно понять проблему, нужно делать что-то больше вдоль этих линий:

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» из выпадающего списка сеттер установит выбранный клиент должен поддержать к «C1» (в этом примере готов только «C1», который был намерен сделать код более легким для чтения), но когда я запускаю приложение, даже если сеттер выбирает «C1», а getter возвращает его, но Combobox показывает « C2 "в качестве выбранного элемента. –

Смежные вопросы