从存储在附加属性中的集合的CollectionChanged事件取消订阅

时间:2011-12-02 15:07:23

标签: c# .net attached-properties inotifycollectionchanged

好的,所以我有一个附加属性(在静态类中声明),它将INotifyCollectionChanged属性附加到对象。

设置属性后,我想开始监视集合的变化,然后对附加集合的对象执行一些动作

首次尝试:

private static void MyProperty_OnChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
    // We need both the dependency object, and the collection args to process the notification
    NotifyCollectionChangedEventHandler changedFunc = (sender, eventArgs) => MyProperty_OnCollectionChanged( d, sender, eventArgs );

    if( e.OldValue != null )
        e.OldValue.CollectionChanged -= changedFunc;   // Can you see the bug?
    if( e.NewValue != null )
        e.NewValue.CollectionChanged += changedFunc;

}

为了将集合附加到处理程序中的对象,我将d拉入闭包。很容易,对吧?

嗯,我相信你可以在这里看到这个错误。当集合被删除或替换为新集合时,它无法取消注册事件处理程序,因为changedFunc是一个具有不同闭包的新处理程序。

那么,这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

从您的代码中,不清楚这种静态方法的位置。

是否有某种方法可以将事件处理程序存储为它所属的类的成员变量?这将是一个单一的参考,可以根据需要添加和删除。每当MyProperty_OnChanged触发时,您正在构建一个新的事件处理程序。

或者,您是否可以更改集合以存储对事件处理程序的引用,以便您可以通过e.OldValue.OldHandler(或类似代码)访问它,以便以后可以访问它?

答案 1 :(得分:0)

我通过使用另一个附加属性来解决此问题,以保存包含事件处理程序和对d的引用的私有对象。实际上,我明确地创建了一个闭包类,并保持对它的引用。

但这对我来说似乎是一个非常沉重的方法,我真的在寻找更优雅的解决方案。