2

INotifyCollectionChanged基本的に標準をラップするだけのカスタムクラスがありますObservableCollection。何かが追加/削除されるたびに、CollectionChanged期待どおりにイベントが発生します。ただし、を使用してこのイベントをリッスンしようとするWeakEventListenerと、リスナーはイベントを受け取りません。なぜこれが起こっているのですか?どうすれば修正できますか?

以下のサンプルでは、​​ aNotImplementedExceptionがスローされることを期待しますが、テスト ケースは成功します (これは、イベントが実際に発生したことを明確に示しています)。コレクションをObservableCollectionではなく に変更するとWrapper、期待どおりに例外がスローされます。

public class Test : IWeakEventListener
{
    private class Wrapper : INotifyCollectionChanged
    {
        private readonly ObservableCollection<string> _internal 
                                     = new ObservableCollection<string>();

        public void Add(string s)
        {
            _internal.Add(s);
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged
        {
            add { _internal.CollectionChanged += value; }
            remove { _internal.CollectionChanged -= value; }
        }
    }

    public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    [Test]
    public void CustomCollectionTest()
    {
        //change to new ObservableCollection<string>() and the exception gets thrown
        var collection = new Wrapper(); 
        var raised = false;
        collection.CollectionChanged += (o, e) => raised = true;
        CollectionChangedEventManager.AddListener(collection, this);
        collection.Add("foobar");
        Assert.True(raised);
    }
}

関連している可能性がありますが、まだ回答がありません:
送信者が公称ではない場合、WeakEventManager がイベントを発生させないのはなぜですか?

4

1 に答える 1

2

理由については、問題はこの質問と同じです。基本的に、イベント マネージャに登録されたソースは、イベントの送信者と同じでなければなりません。

この制限の回避策としてWrapper、ラップされたコレクションでイベントを直接使用するのではなく、 がイベントを送信することを確認する必要があります。

private class Wrapper : INotifyCollectionChanged
{
    private readonly ObservableCollection<string> _internal 
                                 = new ObservableCollection<string>();

    public Wrapper()
    {
        _internal.CollectionChanged += OnInternalChanged;
    }

    public void Add(string s)
    {
        _internal.Add(s);
    }

    private void OnInternalChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        var toRaise = CollectionChanged;
        if (toRaise != null)
            toRaise(this, e);
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;
}
于 2015-03-27T02:24:50.130 に答える