2016-07-21 23 views
0

想,我有下面的類層次結構:INotifyPropertyChanged的鼓入類層次

public NestedClass : INotifyPropertyChanged { 
    string prop1; 

    public String Prop1 { 
     get { return prop1; } 
     set { 
      prop1 = value; 
      OnPropertyChanged("Prop1"); 
     } 
    } 

    void OnPropertyChanged(String name) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

public Class1 : INotifyPropertyChanged { 
    ObservableCollection<NestedClass> collection; 

    public Class1() { 
     collection = new ObservableCollection<NestedClass>(); 
    } 

    public ObservableCollection<NestedClass> Collection { 
     get { return collection; } 
     set { 
      if (collection != null) { 
       collection.CollectionChanged -= childOnCollectionChanged; 
      } 
      collection = value; 
      if (collection != null) { 
       collection.CollectionChanged += childOnCollectionChanged; 
      } 
     } 
    } 

    void childOnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) { 
     switch (e.Action) { 
      case NotifyCollectionChangedAction.Add: 
       ((INotifyPropertyChanged)e.NewItems[0]).PropertyChanged += childOnPropertyChanged; 
       break; 
      case NotifyCollectionChangedAction.Remove: 
       ((INotifyPropertyChanged)e.OldItems[0]).PropertyChanged -= childOnPropertyChanged; 
       break; 
      case NotifyCollectionChangedAction.Reset: 
       if (e.OldItems == null) { break; } 
       foreach (INotifyPropertyChanged itemToRemove in e.OldItems) { 
        itemToRemove.PropertyChanged -= childOnPropertyChanged; 
       } 
       break; 
     } 
    } 
    void childOnPropertyChanged(Object sender, PropertyChangedEventArgs e) { 
     OnPropertyChanged("nested"); 
    } 

    void OnPropertyChanged(String name) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

Class1類,其中包含一些屬性和不同類別的多個集合。所有收藏品的定義與NestedClass的收藏品相同。它們被正確綁定到UI,我在那裏沒有問題。

Class1對象和嵌套的對象/集合可以在運行時創建,也可以由XML解串器生成。爲了正確處理反序列化的集合,我必須在分配集合時訂閱每個集合項目的INotifyPropertyChanged事件。

我的目標是處理NestedClass的所有項目Class1的所有更改以獲取數據已更改的信息(並將此信息傳遞給其父項)。

問題是,我有多個嵌套集合,他們通知父類Class1,它成功地將事件冒泡到其父級。但是,一個集合通知父母Class1有關更改,但Class1中的handler爲空,因爲結果Class1不會將事件冒泡到其父類(此處不顯示爲不相關)。我經歷了調試器,但無法找到問題出在哪裏。當其他嵌套集合調用父節點OnPropertyChanged時,handler不爲null,並且所有內容都正常工作。

編輯:此問題僅在Class1NestedClass對象由XML解串器生成時纔會引發。

我在SO上看了很多類似的帖子,但其中大部分都是關於視圖中無效的DataContext,這不是我的情況(我相信)。還有什麼我可以檢查找到問題的根源?

+0

我懷疑它會幫助你,但你可能想考慮切換到['BindingList '](https://msdn.microsoft.com/en-us/library/ms132679(v = vs.110) .aspx)而不是'ObserveableCollection ',它具有你在'childOnCollectionChanged'中已經內置的邏輯。只要確保'RaiseListChangedEvents'設置爲true,並且ListChanged'事件將隨'args.ListChangedType == ListChangedType.ItemChanged'一起引發,任何時候其中一個成員引發其'PropertyChanged'事件 –

+0

感謝提示!我會詳細閱讀它。但有人聲稱'BindingList'在WPF中沒有得到適當的支持:http://stackoverflow.com/a/4284904/3997611 – Crypt32

+0

對於WPF綁定,BindingList是不必要的(對於您的解決方案也是如此)。當你將一個'DataSource =「{Binding Path = InstanceOfClass1.Collection}''作爲一個列表或一個表格數據源時,那麼在行級別你有'Text =」{Binding Path = Prop1}「'連接到集合中的每一行,您不需要通過冒泡綁定來「幫助」。 BindingLists在WPF中工作正常,它們不會被竊聽,只是它們不是必需的並且會引入開銷。 –

回答

0

您可能需要考慮切換到BindingList<T>而不是ObserveableCollection<T>,它已經在childOnCollectionChanged中進行了邏輯處理。只要確保RaiseListChangedEvents設置爲true,並且ListChanged事件將隨args.ListChangedType == ListChangedType.ItemChanged一起提高,任何時候其中一個成員引發其PropertyChanged事件。

+0

儘管'BindingList'增加了額外的開銷(由於集合中只包含十幾個項目,所以我可以接受),但它正是我需要的,因爲我需要收集項目更改(不僅僅是集合更改)。 – Crypt32