Как обрабатывать CompositeCollection с функциями CollectionView? - PullRequest
6 голосов
/ 17 января 2010

Есть ли способ получить уведомление при изменении текущего местоположения CompositeCollection?

Мне нужно, чтобы CompositeCollection отслеживался CollectionView, любые идеи приветствуются.

Ответы [ 3 ]

6 голосов
/ 17 января 2010

Вы можете определить, когда текущий элемент изменился, отслеживая событие ICollectionView.CurrentChanged вашего CollectionView. У меня работает следующий код:

CompositeCollection cc = new CompositeCollection();
cc.Add(new CollectionContainer { Collection = new string[] { "Oh No!", "Fie" } });
cc.Add(new CollectionContainer { Collection = new string[] { "Zounds", "Ods Bodikins" } });
CollectionViewSource cvs = new CollectionViewSource { Source = cc };

// Subscribing to CurrentChanged on the ICollectionView
cvs.View.CurrentChanged += (o, e) => MessageBox.Show("current changed");

lb.ItemsSource = cvs.View;  // lb is a ListBox with IsSynchronizedWithCurrentItem="True"

Когда я изменяю выбор в ListBox, появляется окно сообщения.

Что касается фильтрации, сортировки и группировки, согласно ответу Арона, они недоступны при просмотре CompositeCollection. Но для справки вот способы обнаружения изменений для представлений, которые делают поддерживают эти функции:

  • Похоже, вы получите событие CollectionChanged при изменении фильтра, хотя я не могу найти это задокументировано.
  • SortDescription - это SortDescriptionCollection, который является INotifyCollectionChanged, поэтому подключите обработчик событий CollectionChanged к свойству SortDescription.
  • GroupDescription равен ObservableCollection<GroupDescription>, поэтому подключите обработчик события CollectionChanged к свойству GroupDescription.
0 голосов
/ 12 июля 2016

Я столкнулся с той же проблемой: мне была нужна сортировка CompositeCollection. Я написал следующий класс, который решает проблему, по крайней мере для ObservableCollections того же типа.

Идея состоит в том, чтобы сохранить составную коллекцию как обычную наблюдаемую коллекцию и обновлять ее при изменении базовых коллекций. Затем полученная коллекция (AllNodes) может быть использована в пользовательском интерфейсе, и она прекрасно поддерживает CollectionView.

using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;

namespace Util {
    public class ObservableCollectionCollector<T> {
        private class ReplacableObservableCollection : ObservableCollection<T> {
            public void Replace(int idx, T v) {
                SetItem(idx, v);
            }
        }
        private readonly ReplacableObservableCollection allNodes;
        private readonly ObservableCollection<T>[] colls;
        private readonly int[] lens;

        public ObservableCollectionCollector(params ObservableCollection<T>[] colls) {
            this.colls = colls;
            allNodes = new ReplacableObservableCollection();
            foreach (var l in colls) {
                foreach (var e in l)
                    allNodes.Add(e);
                l.CollectionChanged += HandleCollectionChanged;
            }
            lens = colls.Select(c => c.Count).ToArray();
        }

        public ReadOnlyObservableCollection<T> AllNodes {
            get { return new ReadOnlyObservableCollection<T>(allNodes); }
        }

        private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            int i0 = 0;
            int ci = 0;
            foreach (var l in colls) {
                if (l == sender)
                    break;
                i0 += l.Count;
                ++ci;
            }
            switch (e.Action) {
                case NotifyCollectionChangedAction.Add:
                    for (int i = 0; i < e.NewItems.Count; ++i)
                        allNodes.Insert(i0 + e.NewStartingIndex + i, (T)e.NewItems[i]);
                    break;
                case NotifyCollectionChangedAction.Move:
                    for (int i = 0; i < e.OldItems.Count; ++i)
                        allNodes.Move(i0 + e.OldStartingIndex + i, i0 + e.NewStartingIndex + i);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    for (int i = 0; i < e.OldItems.Count; ++i)
                        allNodes.RemoveAt(i0 + e.OldStartingIndex);
                    break;
                case NotifyCollectionChangedAction.Replace:
                    for (int i = 0; i < e.NewItems.Count; ++i)
                        allNodes.Replace(i0 + e.OldStartingIndex + i, (T)e.NewItems[i]);
                    break;
                case NotifyCollectionChangedAction.Reset:
                    for (int i = 0; i < lens[ci]; ++i)
                        allNodes.RemoveAt(i0);
                    break;
            }
            lens[ci] = ((ObservableCollection<T>)sender).Count;
        }
    }
}
0 голосов
/ 17 января 2010

Вы не можете запустить CollectionView для совокупной коллекции, см. здесь

...