I've a WPF/Caliburn app which has a ShellView
which includes TabControl
where each TabItem
corresponds to individual ViewModel
(they all inherit Screen
).
Some of those ViewModels
have dispose logic implemented in OnDeactivate
:
protected override void OnDeactivate(bool close)
{
if (close)
_disposeList.Dispose();
base.OnDeactivate(close);
}
ShellViewModel
overrides TryClose
:
public override async void TryClose(bool? dialogResult = default(bool?))
{
// some dispose logic here
base.TryClose(dialogResult);
await Task.Run(() =>
{
// show closing message for 2 sec
using (StartBusy(ViewModelBusyReason.Closing))
{
Thread.Sleep(2000);
}
});
Application.Current.Shutdown();
// Environment.Exit(0);
}
When app closes it only calls OnDeactivate
on 1 or 2 VMs, then app shuts down.
How to guarantee OnDeactivate
to be called on all VMs before app close?
I tried to add Sleep in TryClose
and it didn't work.
And also: is there a canonical Caliburn way to implement TryClose
on ShellViewModel
?
I.e. do I have to call Application.Current.Shutdown()
or Environment.Exit(0)
or neither?
ShellViewModel
definition:
public class ShellViewModel : Conductor<Screen>.Collection.OneActive
{
public ShellViewModel(/*some params here*/)
{
Items.Add(Bootstrapper.Resolve<ViewModelOne>());
Items.Add(Bootstrapper.Resolve<ViewModelTwo>());
Items.Add(Bootstrapper.Resolve<ViewModelThree>());
// ...more VMs here
}
Ok, here is a solution which I finally came up with:
// ShellViewModel
public override void TryClose(bool? dialogResult = default(bool?))
{
_disposeList.Dispose();
while (Items.Any())
DeactivateItem(Items.First(), true);
base.TryClose(dialogResult);
Application.Current.Shutdown();
}
And override OnDeactivate
in each individual VM:
protected override void OnDeactivate(bool close)
{
_disposeList.Dispose();
base.OnDeactivate(close);
}