Search code examples
c#.netattached-propertiesinotifycollectionchanged

Un-subscribing from CollectionChanged event of a collection stored in an attached property


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?


Solution

  • 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.