2012-12-18 146 views
1

我有一个嵌套在DockPanel中的DataGrid。 DockPanel充当数据上下文:检测ObservableCollection是否已被修改

DockPanel1.DataContext = GetData(); 

GetData()方法返回一个ObservableCollection。

ObservableCollection可以在DataGrid中修改,也可以在嵌套在DockPanel中的几个文本框中修改。我也使用DataView浏览集合。

我想检测集合是否已被修改,并在用户尝试关闭应用程序而不保存数据时发出警告。

是否有任何可以使用的内置机制(一种集合上或视图上的“IsDirty”标志)?如果没有,我想我将不得不监视所有的控件并手动检测任何更改。

感谢, 莱谢克

回答

3

为了检测集合本身的变化,你必须附加一个CollectionChanged处理程序。如果还需要检测集合中包含的对象的更改,则必须将PropertyChanged处理程序附加到每个对象(前提是对象实现INotifyPropertyChanged)。

的实现将基本上是这样的:

var collection = GetData(); 
collection.CollectionChanged += OnCollectionChanged; 

... 

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    switch (e.Action) 
    { 
     case NotifyCollectionChangedAction.Add: 
      AddPropertyChanged(e.NewItems); 
      break; 
     case NotifyCollectionChangedAction.Remove: 
      RemovePropertyChanged(e.OldItems); 
      break; 
     case NotifyCollectionChangedAction.Replace: 
     case NotifyCollectionChangedAction.Reset: 
      RemovePropertyChanged(e.OldItems); 
      AddPropertyChanged(e.NewItems); 
      break; 
    } 

    ... 
} 

private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    ... 
} 

private void AddPropertyChanged(IEnumerable items) 
{ 
    if (items != null) 
    { 
     foreach (var obj in items.OfType<INotifyPropertyChanged>()) 
     { 
      obj.PropertyChanged += OnPropertyChanged; 
     } 
    } 
} 

private void RemovePropertyChanged(IEnumerable items) 
{ 
    if (items != null) 
    { 
     foreach (var obj in items.OfType<INotifyPropertyChanged>()) 
     { 
      obj.PropertyChanged -= OnPropertyChanged; 
     } 
    } 
} 
1

为了详细说明上述克莱门斯的回答了一下,下面就来使用这些事件的简单方法(上收集,以及所包含的项目)来实现一个IsDirty标志,如你所描述的:

​​

该代码应该是不言自明的。

当然,您可以删除“where T:INotifyPropertyChanged”以允许不会实现该接口的对象存储在集合中,但是您不会收到有关它们的任何属性更改的通知,因为没有这个界面,他们不能通知你。

而且,如果您想要追踪不仅是集合很脏,而且还需要如何在OnCollectionChanged和OnItemPropertyChanged中记录事件参数中传递的信息,这样做会很好。

+0

谢谢Clemens和Cerebrate。这是我将用于新项目的一个非常好的解决方案。 关于目前的项目,似乎没有返工就无法使用它。首先,我已经在光盘上序列化了一堆ObservableCollections。当我尝试将它们设置为deandlize并将其转换为DirtyCollection时,会抛出异常“Invalid cast”。 其次,我的DirtyCollection有一个成员 - 一个ObservableCollection,也需要是一个DirtyCollection。换句话说,我有一个集合的集合。 我只是希望有一个简单的现成的方法来做到这一点。 – Leszek