1

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?

Mark
  • 1,644
  • 15
  • 25

2 Answers2

0

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?

Joe
  • 38,368
  • 16
  • 103
  • 119
  • As it's an attached property, there is no class I can save the handler as a member of. Currently, I'm storing _another_ object in _another_ attached property to solve this, but I'm looking for a cleaner solution. – Mark Dec 05 '11 at 08:39
  • Also, it's not "my" collection. The attached property should work with any `INotifyCollectionChanged` implementing object. – Mark Dec 05 '11 at 08:43
0

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.

Mark
  • 1,644
  • 15
  • 25