2013-06-30 53 views
0

我有一個類,像這樣:合併兩個集合,並具有從原始館藏事件傳播

Class A 
{ 
    public ObservableCollection<T> collectionA; 
    public ObservableCollection<T> collectionB; 
    public T objectA; 
} 

我要揭發他人財產:

public ObservableCollection<T> All; 

包含所有collectionA,collectionB和對象A的。

起初,我看到我指出對CompositeCollection類的其他問題。但是,如果我這樣做,似乎每當我更改collectionA時,對其的更改都不會導致事件通過CompositeCollection傳播並通知它必然會發生的事情(其中一些實際上是我自己的類)。

所以,我的第二個方法是一個快速和骯髒的功能:

public void HookCollection(ObservableCollection<T> dest, ObservableCollection<T> source) 
     source.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender, NotifyCollectionChangedEventArgs e) 
      { 
       // Apply the same changes to the destination collection 
       if (e.Action == NotifyCollectionChangedAction.Reset) 
       { 
        foreach (T o in source) 
        { 
         dest.Remove(o); 
        } 
       } 
       if (e.NewItems != null) 
       { 
        foreach (T o in e.NewItems) 
        { 
         dest.Add(o); 
        } 
       } 
       if (e.OldItems != null) 
       { 
        foreach (T o in e.OldItems) 
        { 
         dest.Remove(o); 
        } 
       } 
      }); 
    } 

但我很快發現,在「復位」動作,即最初的源集合裏面的物品已被破壞,所以我不知道要從目的地中刪除什麼。

此屬性綁定到具有取決於該列表的內容就可以了一些屬性控制,即...最小和整套的最大值。這些反過來又受到控制。所以能夠作爲一個IEnumerable迭代它將是非常有用的(而CompositeCollection使這很困難)。

因此,我需要被通知更改列表(和子列表)的清潔方式。

目前,我能看到的唯一解決方案是在我的控件類中,檢測CompositeCollection,然後遍歷每個CollectionContainer並附加到它的CollectionChanging事件(如果有)。然而,正如你可以想象的,這是一個相當骯髒的方式來鉤入事件。很高興有一些乾淨地聚合這些事件的方法。 (我認爲這是CompositeCollection,但顯然不是?)。

感謝您的任何想法!

+0

麥,在什麼樣的風格,你會建議使用?返回一個multiValueConverter?或者當我綁定到目標控件時,綁定我的視圖中的所有屬性,並讓轉換器創建所有對象的合併列表?...將它作爲一個屬性公開將是很好的.. 。但它似乎沒有當前選項 – JoshG

+0

實際上更邪惡,MultiValueConverter會有同樣的問題,因爲它不會傳播來自底層容器的事件... – JoshG

回答

0

根據MSDN NotifyCollectionChangedAction.Reset意味着

集合的內容發生了巨大變化。

在這種情況下,event參數不會包含舊項目,因爲重新掃描整個集合並且不處理每個Add Remove事件可能會更有效。

爲了解決你目前的解決方案,所有您需要做的就是添加一個功能RES-掃描您的收藏並運行它時,您會收到NotifyCollectionChangedAction.Reset行動。

private void init() 
    { 
     // if you want it to be thread safe dont forget to lock 
     all.Clear(); 

     foreach (var item in this.collectionA) 
     { 
      all.Add(item); 
     } 
     foreach (var item in this.collectionB) 
     { 
      all.Add(item); 
     } 
    } 

//你鉤住方法應該是這樣的:

public void HookCollection(ObservableCollection<int> dest, ObservableCollection<int> source) 
    { 
    source.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender, NotifyCollectionChangedEventArgs e) 
     { 
      // Apply the same changes to the destination collection 
      if (e.Action == NotifyCollectionChangedAction.Reset) 
      {     
       this.init(); 
      } 
      if (e.NewItems != null) 
      { 
       foreach (int o in e.NewItems) 
       { 
        dest.Add(o); 
       } 
      } 
      if (e.OldItems != null) 
      { 
       foreach (int o in e.OldItems) 
       { 
        dest.Remove(o); 
       } 
      } 
     });   

    } 
+0

這不會工作,但它會嗎?因爲如果我重置其中一個子集合,它會完全重置合併的集合嗎? – JoshG

+0

沒關係,我剛剛發現了這個問題,它清除了那些... http://stackoverflow.com/questions/224155/when-clearing-an-observablecollection-there-are-no-items-in-e-olditems 所以這可能足以讓我走出困境。我最近嘗試過使用CompositeCollectionView進行實驗,但是我無法獲得IEnumerable 。 – JoshG

+0

@JoshG它的工作原理是我測試了它,並且當您清除子集合時,組合集合通過遍歷集合得到更新。 – makc