The Loaded
event is defined on FrameworkElement
and UserControl
is derived from it. That is why this event is raised on the user control.
However, Closing
is defined on Window
. Since a UserControl
does not inherit from Window
this event will never be raised, as it is not even defined.
There is no event in UserControl
that you can reliably use to detect that your view has been replaced. Even the Unloaded
event can be ambiguous here.
Loaded and Unloaded might both be raised on controls as a result of user-initiated system theme changes. A theme change causes an invalidation of the control template and the contained visual tree, which in turn causes the entire control to unload and reload. Therefore Unloaded cannot be assumed to occur only on navigation away from the page.
Note that the Unloaded event is not raised after an application begins shutting down.
A safer way is to define an interface for your view models that provides a method like:
public interface IDisposableViewModel
{
void DisposeViewModel();
}
Implement this interface in your view model to call the logic of your ClosingCommand
. Then in your main window or whereever the navigation logic is implemented either access the view model directly via this interface and call DisposeViewModel()
explicitly before, after or while navigating. If this logic is implemented in the view, e.g. the code behind, you can access the DataContext
of the view your are replacing, check if it implements IDisposableViewModel
and do the same, e.g.:
private void Navigate(UserControl currentView, UserControl nextView)
{
// ...this is just an example, your code definitely differs.
if (currrentView is IDisposableViewModel disposableViewModel)
disposableViewModel.DisposeViewModel();
RemoveView(currentView);
SetView(nextView);
}
The point of it all is that you trigger navigation somewhere in your code and that is the point where you can explicitly clean up or execute any code necessary without any other events.