2012-12-18 196 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