Caliburn Micro:确保在关闭应用程序之前调用所有 OnDeactivates
Caliburn Micro: Ensure that all OnDeactivates were called before app's shutdown
我有一个 WPF/Caliburn 应用程序,它有一个 ShellView
,其中包括 TabControl
,其中每个 TabItem
对应于个人 ViewModel
(它们都继承 Screen
).
其中一些 ViewModels
在 OnDeactivate
中实现了处理逻辑:
protected override void OnDeactivate(bool close)
{
if (close)
_disposeList.Dispose();
base.OnDeactivate(close);
}
ShellViewModel
覆盖 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);
}
当应用程序关闭时,它仅在 1 或 2 个虚拟机上调用 OnDeactivate
,然后应用程序关闭。
如何保证 OnDeactivate
在应用关闭前在所有 VM 上被调用?
我尝试在 TryClose
中添加 Sleep,但没有成功。
还有:是否有一种规范的 Caliburn 方法可以在 ShellViewModel
上实现 TryClose
?
IE。我必须打电话给 Application.Current.Shutdown()
或 Environment.Exit(0)
还是两者都不打电话?
ShellViewModel
定义:
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
}
从 ShellViewModel
的 TryClose
方法调用每个子视图模型的 TryClose
方法:
//ShellViewModel:
public override void TryClose(bool? dialogResult = null)
{
base.TryClose(dialogResult);
//...
foreach (var item in Items)
item.TryClose();
}
此外,任何使用 IDisposable
字段的视图模型都应实现 IDisposable
接口:
public sealed class ViewModelTwo : Screen, IDisposable
{
...
public override void TryClose(bool? dialogResult = null)
{
Dispose();
base.TryClose(dialogResult);
}
public void Dispose()
{
_disposeList?.Dispose();
}
}
好的,这是我最终想出的解决方案:
// ShellViewModel
public override void TryClose(bool? dialogResult = default(bool?))
{
_disposeList.Dispose();
while (Items.Any())
DeactivateItem(Items.First(), true);
base.TryClose(dialogResult);
Application.Current.Shutdown();
}
并在每个单独的 VM 中覆盖 OnDeactivate
:
protected override void OnDeactivate(bool close)
{
_disposeList.Dispose();
base.OnDeactivate(close);
}
我有一个 WPF/Caliburn 应用程序,它有一个 ShellView
,其中包括 TabControl
,其中每个 TabItem
对应于个人 ViewModel
(它们都继承 Screen
).
其中一些 ViewModels
在 OnDeactivate
中实现了处理逻辑:
protected override void OnDeactivate(bool close)
{
if (close)
_disposeList.Dispose();
base.OnDeactivate(close);
}
ShellViewModel
覆盖 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);
}
当应用程序关闭时,它仅在 1 或 2 个虚拟机上调用 OnDeactivate
,然后应用程序关闭。
如何保证 OnDeactivate
在应用关闭前在所有 VM 上被调用?
我尝试在 TryClose
中添加 Sleep,但没有成功。
还有:是否有一种规范的 Caliburn 方法可以在 ShellViewModel
上实现 TryClose
?
IE。我必须打电话给 Application.Current.Shutdown()
或 Environment.Exit(0)
还是两者都不打电话?
ShellViewModel
定义:
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
}
从 ShellViewModel
的 TryClose
方法调用每个子视图模型的 TryClose
方法:
//ShellViewModel:
public override void TryClose(bool? dialogResult = null)
{
base.TryClose(dialogResult);
//...
foreach (var item in Items)
item.TryClose();
}
此外,任何使用 IDisposable
字段的视图模型都应实现 IDisposable
接口:
public sealed class ViewModelTwo : Screen, IDisposable
{
...
public override void TryClose(bool? dialogResult = null)
{
Dispose();
base.TryClose(dialogResult);
}
public void Dispose()
{
_disposeList?.Dispose();
}
}
好的,这是我最终想出的解决方案:
// ShellViewModel
public override void TryClose(bool? dialogResult = default(bool?))
{
_disposeList.Dispose();
while (Items.Any())
DeactivateItem(Items.First(), true);
base.TryClose(dialogResult);
Application.Current.Shutdown();
}
并在每个单独的 VM 中覆盖 OnDeactivate
:
protected override void OnDeactivate(bool close)
{
_disposeList.Dispose();
base.OnDeactivate(close);
}