Reputation: 22956
I have the following line of code in a usercontrol:
Application.Current.RootVisual.MouseLeftButtonDown += RootClicked;
When it's defined the parent usercontrol is no longer collected by the GC or destroyed, the RootClicked event keeps firing even after it should no longer be active.
if I add:
Application.Current.RootVisual.MouseLeftButtonDown -= RootClicked;
The issue is no longer present.
Any ideas why this is? Is there a function I should explicitly remove the event?
Upvotes: 1
Views: 321
Reputation: 1332
What happens: Application.Current.RootVisual.MouseLeftButtonDown event keeps reference to the control in its invocation list so the control is not eligible for collection (since it is referenced by the delegate).
Solution:
Subscribe to Unloaded event after you subscribe to the MouseLeftButtonDown event and unsubscribe form the MouseLeftButtonDown event in the Unloaded event handler:
...
Application.Current.RootVisual.MouseLeftButtonDown += RootVisual_MouseLeftButtonDown;
this.Unloaded += Control_Unloaded;
...
void Control_Unloaded(object sender, RoutedEventArgs e)
{
Application.Current.RootVisual.MouseLeftButtonDown -= RootVisual_MouseLeftButtonDown;
}
OR more concise:
Application.Current.RootVisual.MouseLeftButtonDown += RootVisual_MouseLeftButtonDown;
this.Unloaded += (s, e) => Application.Current.RootVisual.MouseLeftButtonDown -= RootVisual_MouseLeftButtonDown;
Upvotes: 2
Reputation: 441
This is a known behavior, but most developers are not aware of it. You should look into the Weak Event Pattern for information on how to get around this limitation in a more graceful (if more coding-intensive) fashion than having to manually remove event handlers.
Upvotes: 1
Reputation: 9070
This is a normal behaviour and a common source of memory leaks in .NET.
When you attach an instance method of object A to an event of object B, you are adding in the list of event receivers the instance of A, so the garbage collector cannot free up the object A until you remove the handler or you release every reference to both object A and B. This is an expected and normal behaviour.
There are two common ways to solve the problem:
1) You unsubscribe object A from the event when you don't need the object A anymore.
2) You use weak events, like WPF does. Weak events are usually implemented with the class WeakReference, you can find more informations on the web.
Upvotes: 3