2012-03-22 5 views
2

ComboBoxのItemsSourceがObservableCollectionにリンクされた新しい(デフォルトではなく)ListCollectionViewにバインドされています。 ComboBox SelectedItemプロパティは、Public SelectedHatプロパティにバインドされています。ComboBoxのSelectedItemが実際に値の前にヌルに設定されています

手順1:コンボボックスの2番目の項目を選択します。 SelectedHatは、リストの2番目のハットになりました。 ステップ2:(ボタンをクリックします)リストの2番目のスポットを新しいハットに設定します。 SelectedHatは最初にnullに設定され、新しいハットに設定されます。

なぜ新しいハットの前にSelectedHatがnullに設定されていますか?

は、私はそれが空白
(2)のみ設定SelectedHatに行くのではなく、選択したvm.Collection [インデックス] =新しいハット()とコンボボックスは、インデックスが選択したこと場合
は (1)、続けることができるようにしたいです一度新しい帽子、NULLの代わりにして、新しい帽子

C#へ:

public partial class MainWindow : Window 
{ 
    private readonly ViewModel vm; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     vm = new ViewModel(); 
     DataContext = vm; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Hat item = new Hat { Name = "hat 2", Color = "Red"}; 
     vm.Collection[1] = item; 
    } 
} 

public class ViewModel : BaseNotifyPropertyChanged 
{ 
    public ObservableCollection<Hat> Collection { get; set; } 
    public ListCollectionView View { get; set; } 

    private Hat selectedHat; 
    public Hat SelectedHat 
    { 
     get { return selectedHat; } 
     set 
     { 
      selectedHat = value; 
      Console.WriteLine(string.Format("SelectedHat set to [{0}]", value)); 
      NotifyPropertyChanged("SelectedHat"); 
     } 
    } 

    public ViewModel() 
    { 
     Collection = new ObservableCollection<Hat>() 
     { 
      new Hat { Name = "hat 1", Color = "Black" }, 
      new Hat { Name = "hat 2", Color = "Black" }, 
      new Hat { Name = "hat 3", Color = "Black" }, 
     }; 

     View = new ListCollectionView(Collection); 
     View.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); 
    } 
} 

public class Hat 
{ 
    public string Name { get; set; } 
    public string Color { get; set; } 

    public override string ToString() 
    { 
     return string.Format("{0} ({1})", Name, Color); 
    } 
} 

public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

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

XAML:

<StackPanel> 
    <TextBlock Text="{Binding Path=SelectedHat, Mode=OneWay}" /> 
    <ComboBox ItemsSource="{Binding Path=View}" SelectedItem="{Binding Path=SelectedHat, UpdateSourceTrigger=PropertyChanged}" /> 
    <Button Content="click me" Click="Button_Click" /> 
</StackPanel> 

答えて

2

あなたはそれがOnPropertyChanged("Item[]")を上昇させ、その後、OnCollectionChanged(NotifyCollectionChangedAction.Replace, (object) obj, (object) item, index)見ることができるので、これはObservableCollection.SetItem

protected override void SetItem(int index, T item) 
{ 
    this.CheckReentrancy(); 
    T obj = this[index]; 
    base.SetItem(index, item); 
    this.OnPropertyChanged("Item[]"); 
    this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, (object) obj, (object) item, index); 
} 

の実装です。 OnCollectionChangedには、 'oldItem'と 'newItem'というパラメータがあります。コードをコンボボックスの実装に追いかけると、古いアイテムが削除され、nullに置き換えられ、新しいアイテムが挿入されていることがわかります。これがあなたの体験している動作を取得する理由です(私も同様です)。

私の回避策では、アイテムを置き換えたり、新しいアイテムを追加したり、現在選択されているアイテムを変更したり、古いアイテムを削除したりするのではなく、アイテムの直接

private void ButtonClick(object sender, System.Windows.RoutedEventArgs e) 
{ 
    Hat newHat = new Hat { Name = "hat 2", Color = "Red" }; 

    var viewModel = (ViewModel)DataContext; 

    var oldHat = viewModel.Collection[1]; 

    if (viewModel.SelectedHat == oldHat) 
    { 
     viewModel.Collection.Add(newHat); 
     viewModel.SelectedHat = newHat; 
     viewModel.Collection.Remove(oldHat); 
    } 
    else 
    { 
     viewModel.Collection[1] = newHat; 
    } 
} 
+0

私の答えを見てください。項目を直接更新し、OnCollectionChangedへの呼び出しはありません。 – Paparazzi

+0

はい、私が言ったことはあなたが提案したもの以外の回避策です:-) – Phil

0

変更。私はちょうどそれをテストした。 vm.Collection [1] .name = "hat 2"

関連する問題