もっとコレクションをプロパティとして使用すると、ObserverableCollectionのCollectionChangedイベントが常に機能しないのはなぜですか?質問について
まず、私はC#に多少新たなんだ...空気私は明確にしましょう。私が取り組んでいるアプリケーションでこの問題にぶつかりました。この特定のクラスはObservableCollectionsをPropertiesとして公開していたので、ObservervableCollectionには独自のイベントがあるので、PropertyChangedイベントは必要ありませんでした。最初の試みは美しく働いた。それから、私はコードを整理し始めました。私は本当にバッキング・バールを必要としないことがわかったので、すべてをメソッドに移しました...そしてUIを更新しなくなりました。 INotifyPropertyChangedを追加すると問題は解決しましたが、私は非常に大きな「WHY?」と残されました。
ここで私が把握できるものを見るためにまとめたテストコードを示します。それは悪い習慣で散らばっていることをお勧めしますが、私は実際にはいつCollectionChangedに依存できるか、PropertyChagnedを追加する必要があるかを把握しようとしています。私はPropertyChangedをCollectionChangedに依存する必要がありますか?そうでなければ、ObservableCollectionのオーバーヘッドは本当に必要ないので、別のList型を使用するべきです。本当に両方を使うのは無駄なようです。
ここでコード
private TestClass test = new TestClass();
public MainWindow()
{
InitializeComponent();
this.DataContext = test;
}
internal class TestClass : INotifyPropertyChanged
{
public ObservableCollection<String> test1 = new ObservableCollection<String>();
public ObservableCollection<String> test2 = new ObservableCollection<String>() { "T2-A" };
public TestClass()
{
}
public ObservableCollection<String> Test1 { get => test1; set { } }
public ObservableCollection<String> Test2 { get => test2; set { this.test2 = value; } }
public ObservableCollection<String> Test3 { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void BT1_Click(object sender, RoutedEventArgs e)
{
//Both of these work fine
test.test1.Add("T1-A");
test.Test1.Add("T1-B");
//First line works...Second line breaks it... but there is a setter.
test.Test2.Add("T2-C");
test.Test2 = new ObservableCollection<String>() { "T2-A", "T2-B" };
test.test2.Add("T2-D");
//First Line throws Null exception... So it's not creating a backing var of it's own.
//test.Test3.Add("T3-A");
var t3 = new ObservableCollection<String>() { "T3-B", "T3-C" };
test.Test3 = t3;
test.Test3.Add("T3-D");
//It updates when I trigger the property changed...but what broke CollectionChanged
test.OnPropertyChanged(nameof(test.Test3));
}
の大部分は、誰もが
<ListBox ItemsSource="{Binding Test1}" HorizontalAlignment="Left" Height="205" VerticalAlignment="Top" Width="161" Margin="10,5,0,0" />
<ListBox ItemsSource="{Binding Test2}" Height="205" Margin="186,5,187,0" VerticalAlignment="Top" />
<ListBox ItemsSource="{Binding Test3}" Height="205" Margin="366,5,8,0" VerticalAlignment="Top" />
<Button x:Name="bT1" Content="Test It" HorizontalAlignment="Left" Height="33" Margin="10,215,0,0" VerticalAlignment="Top" Width="516" Click="BT1_Click" />
私の調査結果、これまで
興味を持っている場合、それはどうかと思われるXAMLですObservableCollectionを使用したいctionChangedイベントでは、バッキングvarを作成し、Collectionのインスタンスを変更しないでください。つまり、 'var col = new ObservableCollection()'ではなく、Clear()を使用してワイプと再構築を行います。私が紛失しているものはありますか? TwoWayのデータを見ると、これはむしろ薄れてくると思います。誰かがtest2の2行目に沿ってコードを壊すのを防ぐ方法はありますか?
あなたは何も欠けていません。この物件を決して公共のセッターに与えないでください。それは起こるのを待っている事故です。これは、コレクションオブジェクトを公開するプロパティの場合には一般的に当てはまりますが、このオブジェクトはうまくいきます。外部コードが使用されるコレクションオブジェクトを決定する必要がある場合は、コンストラクタを介して渡す必要があります。そのため、一度しか設定できません。裏返しフィールド 'readonly'を宣言してそれを釘付けにします。 –