0

ObservableCollections.CollectionChangedイベントのx個をチェーン化し、Nレベルのオブジェクトツリーとしてコンシューマが聞くことができる単一の親レベルのCollectionChangedイベントに公開する方法を確認しようとしていますか?基本的に、すべての子CollectionChangedイベントを一番上の親まで漏斗またはバブルしたい。同様の問題に取り組んでいることに私が気づいた解決策のいくつかは、固定された数のレベルを仮定しています。私はあらゆる深さのレベルをサポートすることを考えています。Chain CollectionChangedイベント

元々、私はFieldInfosのインスタンスを子コンストラクタに渡して直接ハンドラにアタッチすることができたと思っていました。しかし、私は「イベントを示すエラーを取得する 『て、CollectionChanged』は+ =またはの左側に表示されることができます - 。=

おかげで、

public class FieldInfos 
    { 
     public event NotifyCollectionChangedEventHandler CollectionChanged; 

     private ObservableCollection<Field> _fields; 

     public ObservableCollection<Field> Fields => _fields ?? (_fields = new ObservableCollection<Field>()); 
    } 



    public class Field 
    { 
     public string Name; 

     private ObservableCollection<FieldInstance> _instances; 
     public ObservableCollection<FieldInstance> Instances => _instances ?? (_instances = new ObservableCollection<FieldInstance>()); 
    } 

    public class FieldInstance 
    { 
     public string Id { get; set; } 
    } 
+0

この作業を行うには、ObservableCollection <> 'を変更する必要があります。さもなければ、それを行うためのファサードパターンを作成することができます - あなたは内部的な 'ObservableCollection <>'をラップするあなた自身の 'NestedObservableCollection <>'クラスを作ることになります。 – Enigmativity

+0

あなたの提案が可能な解決策であることを示すサンプルコードを提供してもよろしいですか? – Mike

+1

@Mikeあなたはそれを試しましたか? – Asti

答えて

1

最も簡単な方法は、元ObservableCollection<T>をサブクラスである

あなたは、共分散の問題を回避するために、少なくとも1つのインタフェースを必要と思います。また、INotifyDescendantsChangedインタフェースを実装する独自のクラスを持つことができます。

public interface INotifyDescendantsChanged 
{ 
    event NotifyCollectionChangedEventHandler DescendantsChanged; 
} 

public class ObservableBubbleCollection<T> : ObservableCollection<T>, INotifyDescendantsChanged 
{ 
    public event NotifyCollectionChangedEventHandler DescendantsChanged; 
    protected virtual void OnDescendantsChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     NotifyCollectionChangedEventHandler handler = DescendantsChanged; 
     if (handler != null) 
      handler(sender, e); 
    } 

    private readonly Func<T, INotifyDescendantsChanged> childSelector; 
    public ObservableBubbleCollection() { } 
    public ObservableBubbleCollection(Func<T, INotifyDescendantsChanged> childSelector) 
    { 
     this.childSelector = childSelector; 
    } 

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     base.OnCollectionChanged(e); 
     OnDescendantsChanged(this, e); 

     if (childSelector == null) 
      return; 

     if (e.NewItems != null) 
      foreach (var item in e.NewItems.Cast<T>()) 
       childSelector(item).DescendantsChanged += OnDescendantsChanged; 

     if (e.OldItems != null) 
      foreach (var item in e.OldItems.Cast<T>()) 
       childSelector(item).DescendantsChanged -= OnDescendantsChanged; 
    } 
} 

これを使用するには、ObservableCollectionのインスタンスを置き換え、セレクタをコレクションに渡します。

public class FieldInfos 
{ 
    private ObservableBubbleCollection<Field> _fields; 

    public ObservableBubbleCollection<Field> Fields => _fields ?? (_fields = new ObservableBubbleCollection<Field>(fi => fi.Instances)); 
} 

public class Field 
{ 
    public string Name; 

    private ObservableBubbleCollection<FieldInstance> _instances; 
    public ObservableBubbleCollection<FieldInstance> Instances => _instances ?? (_instances = new ObservableBubbleCollection<FieldInstance>()); 
} 

public class FieldInstance 
{ 
    public string Id { get; set; } 
} 

static class Program 
{ 
    static void Main(string[] args) 
    { 
     var fi = new FieldInfos(); 
     fi.Fields.DescendantsChanged += (sender, e) => 
     { 
      Console.WriteLine("Change from {0}", sender.GetType()); 
     }; 

     var field = new Field(); 
     fi.Fields.Add(field); 

     field.Instances.Add(new FieldInstance()); 
     Console.ReadLine(); 
    } 
} 
+0

アスティ、これは最高です。ソリューションを説明するために提供した非常に完全なコードサンプル。私と将来来る人にこれを提供する時間を取ってくれて本当に感謝します。にスポット! – Mike

+0

@Mike大歓迎です、マイク。ちょうどそのクリスマスの精神の一部を渡す! :) – Asti

関連する問題