2012-11-02 6 views
11

Mieć pęk ObservableCollection<MeClass> Result i wymagać połączenia ich wszystkich w inne ObservableCollection<MeClass> AllResults, dzięki czemu mogę wyświetlić je w postaci listview.Wiązanie wielu obserwowalnych kolczyków z jedną obserwowalną kolekcją

Tylko nie wiem, jak połączyć je wszystkie w jednym.

Stworzyłem nową klasę, aby połączyć je wszystkie, ale nie jestem pewien, jak zostaną zaktualizowane po tym, jak dostałem listę raz ... Tak więc nie jestem pewien, który kierunek wybrać.

Wiem o INotifyPropertyChanged Po prostu nie jestem pewien, jak je wszystkie połączyć i aktualizować, jak wszystko się zmienia.

Odpowiedz

21

NET ma CompositeCollection który pozwala leczyć wiele zbiorów w jednej kolekcji. Implementuje on kod INotifyCollectionChanged, o ile twoje wewnętrzne kolekcje implementują także INotifyCollectionChanged (co w twoim przypadku na pewno czyni), twoje powiązania powinny działać bez żadnych problemów. Przykładem

Zastosowanie:

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

Należy zauważyć, że nie można używać grupowania z 'CompositeCollectionView'. To 'CanGroup' ma wartość' false', a właściwość 'ICollectionView.GroupDescriptions' ma wartość' null' i nie można jej ustawić. –

3

Coś takiego?

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

Nie trzeba wyważać otwartych drzwi - NET już CompositeCollection (patrz moja odpowiedź). –

+0

Nie natknąłem się na to! Bardzo przydatne, dziękuję! – GazTheDestroyer

+1

To podejście działa z grupowaniem, w przeciwieństwie do wbudowanego w strukturę 'CompositeCollection'. Dzięki. BTW symbole 'All' w' AddSubCollections' są błędami kompilacji. –

0

I przerobiony @ odpowiedź GazTheDestroyer jest w to (wymaga 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); 
     } 
    } 
}