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