将多个ObservableCollection绑定到一个ObservableCollection

18

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

只是不确定如何将它们合并成一个。

我创建了一个新类来将它们全部合并在一起,但不确定在获取列表后它们将如何更新...所以不确定应该采取哪个方向。

我知道关于INotifyPropertyChanged,只是不确定如何将它们全部合并并随着所有更改进行更新。

3个回答

30

.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);

4
请注意,您无法在CompositeCollectionView中使用分组。它的CanGroupfalse,其ICollectionView.GroupDescriptions属性为null且不可设置。 - Drew Noakes

4
像这样的内容吗?
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(请参见我的答案)。 - Adi Lester
2
这种方法适用于分组,不同于框架内置的CompositeCollection。谢谢。顺便说一下,在AddSubCollections中的All符号是编译错误。 - Drew Noakes

4

我将 @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);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接