上記のクレメンスの答えを少し詳しく説明するために、これらのイベント(コレクションおよび含まれるアイテム)を使用して、説明したような IsDirty フラグを実装する簡単な方法を次に示します。
public class DirtyCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
{
private bool isDirty = false;
public bool IsDirty
{
get { return this.isDirty; }
}
public void Clean()
{
this.isDirty = false;
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
// We aren't concerned with how the collection changed, just that it did.
this.isDirty = true;
// But we do need to add the handlers to detect property changes on each item.
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.AddPropertyChanged(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
this.RemovePropertyChanged(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
this.RemovePropertyChanged(e.OldItems);
this.AddPropertyChanged(e.NewItems);
break;
}
base.OnCollectionChanged(e);
}
private void AddPropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged += OnItemPropertyChanged;
}
}
}
private void RemovePropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged -= OnItemPropertyChanged;
}
}
}
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// A property of a contained item has changed.
this.isDirty = true;
}
}
コードはかなり自明である必要があります。
もちろん、「where T : INotifyPropertyChanged」を削除して、そのインターフェイスを実装していないオブジェクトをコレクションに格納できるようにすることもできますが、そのインターフェイスがない場合と同様に、オブジェクトのプロパティの変更が通知されません。 、彼らはあなたにそれらを通知することはできません。
また、コレクションがダーティであることだけでなく、その方法も追跡したい場合は、イベント引数で渡された情報を記録する OnCollectionChanged および OnItemPropertyChanged のいくつかの追加が適切に行われます。