wpf 将多个 ObservableCollection 绑定到一个 ObservableCollection

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13203795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:03:31  来源:igfitidea点击:

Binding multiple ObservableCollections to One ObservableCollection

c#.netwpfobservablecollectioninotifypropertychanged

提问by Reza M.

Have a bunch of ObservableCollection<MeClass> Resultand require to combine them all into another ObservableCollection<MeClass> AllResultsso I can display it in a listview.

有一堆ObservableCollection<MeClass> Result并要求将它们全部组合成另一个,ObservableCollection<MeClass> AllResults以便我可以将它显示在listview.

Just not sure how to combine them all in one.

只是不确定如何将它们合二为一。

I Created a new class to combine them all but not sure how they will get updated after I got the list once... So not really sure which direction to take.

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

I know about INotifyPropertyChangedI'm just not sure how to combine them all and keep updating as everything changes.

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

回答by Adi Lester

.NET has a CompositeCollectionthat allows you to treat multiple collections as a single collection. It implements INotifyCollectionChanged, so as long as your inner collections implement INotifyCollectionChangedas well (which in your case they certainly do), your bindings should work without any problems.

.NETCompositeCollection允许您将多个集合视为一个集合。它实现了INotifyCollectionChanged,所以只要您的内部集合也实现INotifyCollectionChanged了(在您的情况下它们肯定会实现),您的绑定应该可以正常工作。

Usage example:

用法示例:

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

回答by GazTheDestroyer

Something like this?

像这样的东西?

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;
        }
    }
}

回答by Drew Noakes

I reworked @GazTheDestroyer's answer into this (requires C# 7):

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