I have WPF behavior
on specific control. When I close the window that hold the control the OnDetaching
function is not called.
The behavior continues to exist (because of the events to which it's registered), although the window does not exist anymore (memory leak).
Why does the OnDetaching
function not fire, and how can I solve it?
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_PlotAreaMouseLeftButtonDown;
this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_PlotAreaMouseLeftButtonUp;
this.AssociatedObject.MouseMove += AssociatedObject_PlotAreaMouseMove;
}
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_PlotAreaMouseLeftButtonDown;
this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_PlotAreaMouseLeftButtonUp;
this.AssociatedObject.MouseMove -= AssociatedObject_PlotAreaMouseMove;
}
The OnAttached
is called when XAML parser parses XAML and creates an instance of a behaviour that adds to the BehaviorCollection of the target control which is exposed as DependencyAttached property.
However when if the view is disposed, the collection (Behavior collection) was disposed of, it will never trigger OnDetaching method.
If the behaviour is not properly cleanup it will not be collected by GC and will also hold BehaviorCollection and other behaviors in that collection. The behaviours are designed to extend AssociatedObject, as long as you are subscribing to AssociatedObject events its fine as the AssociatedObject (publisher) will die and your behaviour will be collected by garbage collector.
A good source.
An alternative is to handle the "Closing" event (when a user clicks the upper right 'X' button) of the window, and OnDetaching
there.
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding CloseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Then associate the handler in the View constructor:
MyWindow()
{
// Set up ViewModel, assign to DataContext etc.
Closing += viewModel.OnWindowClosing;
}
And add the handler to the ViewModel:
public void OnWindowClosing(object sender, CancelEventArgs e)
{
// Cancel, OnDetaching, etc
}
Try to subscribe to AssociatedObject.Unloaded event and inside the eventHander unsubscribe to all the mouse events. Behaviors OnDetaching() func. not always invoked at "time".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With