2012-11-02 94 views
11

有一堆ObservableCollection<MeClass> Result并需要将它们全部合并为另一个ObservableCollection<MeClass> AllResults,以便我可以将它显示在listview中。将多个ObservableCollections绑定到一个ObservableCollection

只是不知道如何将它们合为一体。

我创建了一个新的类来组合他们所有的人,但不知道他们将如何得到更新后,我得到了一次......所以不知道要采取哪个方向。

我知道关于INotifyPropertyChanged我只是不确定如何将它们全部结合起来,并随着一切变化而不断更新。

回答

21

.NET有一个CompositeCollection,它允许您将多个集合视为一个集合。它实现INotifyCollectionChanged,所以只要你的内部集合实现INotifyCollectionChanged(在你的情况下它们当然可以),你的绑定应该没有任何问题。

用例:

CompositeCollection cc = new CompositeCollection(); 
CollectionContainer container1 = new CollectionContainer() { Collection = Result1 } 
CollectionContainer container2 = new CollectionContainer() { Collection = Result2 } 
cc.Add(container1); 
cc.Add(container2); 
+2

请注意,您不能使用“CompositeCollectionView”进行分组。它的'CanGroup'是'false',它的'ICollectionView.GroupDescriptions'属性是'null'并且是不可设置的。 –

3

像这样的东西?

public class CompositeCollection : ObservableCollection<MeClass> 
{ 
    private ObservableCollection<MeClass> _subCollection1; 
    private ObservableCollection<MeClass> _subCollection2; 

    public CompositeCollection(ObservableCollection<MeClass> subCollection1, ObservableCollection<MeClass> subCollection2) 
    { 
     _subCollection1 = subCollection1; 
     _subCollection2 = subCollection2; 

     AddSubCollections(); 
     SubscribeToSubCollectionChanges(); 
    } 

    private void AddSubCollections() 
    { 
     AddItems(_subCollection1.All); 
     AddItems(_subCollection2.All); 
    } 

    private void AddItems(IEnumerable<MeClass> items) 
    { 
     foreach (MeClass me in items) 
      Add(me); 
    } 

    private void RemoveItems(IEnumerable<MeClass> items) 
    { 
     foreach (MeClass me in items) 
      Remove(me); 
    } 

    private void SubscribeToSubCollectionChanges() 
    { 
     _subCollection1.CollectionChanged += OnSubCollectionChanged; 
     _subCollection2.CollectionChanged += OnSubCollectionChanged; 
    } 

    private void OnSubCollectionChanged(object source, NotifyCollectionChangedEventArgs args) 
    { 
     switch(args.Action) 
     { 
      case NotifyCollectionChangedAction.Add: AddItems(args.NewItems.Cast<MeClass>()); 
                 break; 

      case NotifyCollectionChangedAction.Remove: RemoveItems(args.OldItems.Cast<MeClass>()); 
                 break; 

      case NotifyCollectionChangedAction.Reset: Clear(); 
                 AddSubCollections(); 
                 break; 
     } 
    } 
} 
+2

无需推倒重来 - .NET将已经拥有CompositeCollection(见我的回答)。 –

+0

没有碰到过!非常有用,谢谢! – GazTheDestroyer

+1

与框架的内置'CompositeCollection'不同,此方法适用于分组。谢谢。顺便说一下'AddSubCollections'中的'All'符号是编译错误。 –

0

我返工@ GazTheDestroyer的回答到这个(需要C#7):

internal sealed class CompositeObservableCollection<T> : ObservableCollection<T> 
{ 
    public CompositeObservableCollection(INotifyCollectionChanged subCollection1, INotifyCollectionChanged subCollection2) 
    { 
     AddItems((IEnumerable<T>)subCollection1); 
     AddItems((IEnumerable<T>)subCollection2); 

     subCollection1.CollectionChanged += OnSubCollectionChanged; 
     subCollection2.CollectionChanged += OnSubCollectionChanged; 

     void OnSubCollectionChanged(object source, NotifyCollectionChangedEventArgs args) 
     { 
      switch (args.Action) 
      { 
       case NotifyCollectionChangedAction.Add: 
        AddItems(args.NewItems.Cast<T>()); 
        break; 
       case NotifyCollectionChangedAction.Remove: 
        RemoveItems(args.OldItems.Cast<T>()); 
        break; 
       case NotifyCollectionChangedAction.Reset: 
        Clear(); 
        AddItems((IEnumerable<T>)subCollection1); 
        AddItems((IEnumerable<T>)subCollection2); 
        break; 
       case NotifyCollectionChangedAction.Replace: 
        RemoveItems(args.OldItems.Cast<T>()); 
        AddItems(args.NewItems.Cast<T>()); 
        break; 
       case NotifyCollectionChangedAction.Move: 
        throw new NotImplementedException(); 
       default: 
        throw new ArgumentOutOfRangeException(); 
      } 
     } 

     void AddItems(IEnumerable<T> items) 
     { 
      foreach (var me in items) 
       Add(me); 
     } 

     void RemoveItems(IEnumerable<T> items) 
     { 
      foreach (var me in items) 
       Remove(me); 
     } 
    } 
} 
相关问题