0

私は次のようなクラスを持っています:

Class A
{
    public ObservableCollection<T> collectionA;
    public ObservableCollection<T> collectionB;
    public T objectA;
}

別のプロパティを公開したい:

public ObservableCollection<T> All;

collectionA、collectionB、objectA のすべてが含まれています。

最初に、CompositeCollection クラスを指し示す他の質問を見ました。ただし、これを行うと、collectionA を変更するたびに、その変更によって CompositeCollection を介してイベントが伝播されず、バインドされていることが通知されないように見えます (これらのいくつかは、実際には自分のクラスです)。

したがって、私の 2 番目のアプローチは、迅速で汚い関数でした。

    public void HookCollection(ObservableCollection<T> dest, ObservableCollection<T> source)
        source.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                // Apply the same changes to the destination collection
                if (e.Action == NotifyCollectionChangedAction.Reset)
                {
                    foreach (T o in source)
                    {
                        dest.Remove(o);
                    }   
                }
                if (e.NewItems != null)
                {
                    foreach (T o in e.NewItems)
                    {
                        dest.Add(o);
                    }
                }
                if (e.OldItems != null)
                {
                    foreach (T o in e.OldItems)
                    {
                        dest.Remove(o);
                    }
                }  
            });
    }

しかし、「リセット」アクションで、元のコレクション内にあったアイテムが既に破棄されていることがすぐにわかりました。そのため、宛先コレクションから何を削除すればよいかわかりません。

このプロパティは、このリストの内容に依存するいくつかのプロパティを持つコントロールにバインドされます。つまり、セット全体の最小値と最大値です。これらは、コントロールにバインドされます。そのため、IEnumerable として反復処理できると非常に便利です (そして CompositeCollection はこれを困難にします)。

そのため、リスト (およびサブリスト) への変更を明確に通知する方法が必要です。

現時点では、私が見ることができる唯一の解決策は、CompositeCollection を検出し、次に各 CollectionContainer を反復処理し、CollectionChanging イベントがある場合はその CollectionChanging イベントにアタッチすることです。ただし、ご想像のとおり、これはイベントにフックするためのかなり厄介な方法です。これらのイベントをきれいに集約する何らかの方法があるとよいでしょう。(私はそれが CompositeCollection だと思っていましたが、どうやらそうではありませんか?)。

ご意見ありがとうございます。

4

1 に答える 1

0

MSDN NotifyCollectionChangedAction.Reset によると、

コレクションの内容が劇的に変わりました。

この場合のイベント引数には古いアイテムは含まれません。コレクション全体を再スキャンし、各 Add Remove イベントを処理しない方がおそらく効率的だからです。

現在のソリューションを修正するには、コレクションを再スキャンし、NotifyCollectionChangedAction.Reset アクションを受け取ったときに実行する関数を追加するだけです。

private void init()
    {
        // if you want it to be thread safe dont forget to lock
        all.Clear();

        foreach (var item in this.collectionA)
        {
            all.Add(item);
        }
        foreach (var item in this.collectionB)
        {
            all.Add(item);
        }
    }

//フック メソッドは次のようになります。

public void HookCollection(ObservableCollection<int> dest, ObservableCollection<int> source)
   {
    source.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender, NotifyCollectionChangedEventArgs e)
        {
            // Apply the same changes to the destination collection
            if (e.Action == NotifyCollectionChangedAction.Reset)
            {                   
                this.init();
            }
            if (e.NewItems != null)
            {
                foreach (int o in e.NewItems)
                {
                    dest.Add(o);
                }
            }
            if (e.OldItems != null)
            {
                foreach (int o in e.OldItems)
                {
                    dest.Remove(o);
                }
            }  
        });        

    }
于 2013-06-30T12:38:00.700 に答える