ответ

6

Вы можете определить, когда текущий элемент был изменен путем наблюдения за событием вашего 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 при изменении фильтра, хотя я не могу найти это документированы.
  • SortDescriptions - это SortDescriptionCollection, который является INotifyCollectionChanged, поэтому подключите обработчик событий CollectionChanged в свойстве SortDescriptions.
  • GroupDescriptions - ObservableCollection<GroupDescription>, поэтому подключите обработчик события CollectionChanged в свойстве GroupDescriptions.
+0

Проблема заключается в том, что я использую CompositeCollection, который связан с двумя различными объектами CollectionViewSource. Когда я изменил местоположение в ListBox (который IsSynchronizedWithCurrentItem, очевидно, установлен в True), CurrentChanging (ed) не запускается. – Shimmy

+0

Итак, у вас есть два CVS над одной и той же коллекцией? Тупой вопрос, но вы уверены, что подписались на мероприятие по правильному CVS.View? Предложите вам обновить вопрос, чтобы показать код, который не работает. – itowlson

+0

Возможно, вы скажете мне, как это сделать. Требуется отслеживание CurrentChanging. Вывод из всех моих попыток: событие не увольняется. это не глупый вопрос, я думаю, что это сложнее, чем есть; Мне жаль, что это не так. – Shimmy

0

вы не можете запустить CollectionView на коллекции copmposite см here

+0

Сортировка и фильтрация для меня менее важны. Главным приоритетом является CurrentChanging. BTW взгляните на мою дискуссию с itowlson выше, он говорит, что скоро он отправит код. давайте надеяться на godies ... – Shimmy

+0

Вы можете, потому что так работает валюта - не осознавали ограничений, хотя - спасибо! – itowlson

0

Я столкнулся с той же проблемой: я нуждался в сортировке 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; 
     } 
    } 
}