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

发布于 2024-12-19 03:35:02 字数 841 浏览 2 评论 0原文

好的,我有一个附加属性(在静态类中声明),它将 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是具有不同闭包的新处理程序。

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

Ok, so I have an attached property (declared in a static class) which attaches an INotifyCollectionChanged property to an object.

When the property is set, I want to start monitoring the collection for changes, and then perform some action on the object to which the collection is attached.

First attempt:

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;

}

In order to get the object the collection is attached to into the handler, I pull d into the closure. Easy enough, right?

Well, I'm sure you can see the bug here. When the collection is removed or replaced with a new collection, it fails to un-register the event handler, because changedFunc is a new handler with a different closure.

So, what's the right way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱情眠于流年 2024-12-26 03:35:02

从您的代码中,不清楚这个静态方法位于何处。

有什么方法可以将事件处理程序存储为其所属类的成员变量吗?这将是一个可以根据需要添加和删除的单一参考。当前,每次 MyProperty_OnChanged 触发时,您都会构建一个新的事件处理程序。

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

From your code, it's not clear where this static method lives.

Is there some way you can store the event handler as a member variable of the class it belongs to? That would be a singular reference that could be added and removed as necessary. You are currently constructing a new event handler each time MyProperty_OnChanged fires.

Alternately, can you change your collection to store a reference to the event handler such that you can access it through e.OldValue.OldHandler (or similar) so you would have access to it later?

み零 2024-12-26 03:35:02

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

但这对我来说似乎是一个相当严厉的方法,我真的在寻找一个更优雅的解决方案。

I solved this by using another attached property to hold a private object containing the event handler and reference to d. Effectively I'm explicitly creating a closure class, and keeping a reference to it.

But this seems a pretty heavy handed approach to me, I was really looking for a more elegant solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文