我有一个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
,然后应用关闭
如何保证在app关闭之前在所有VM上调用OnDeactivate
?
我试图在TryClose
中添加Sleep并且它不起作用。
并且:是否有规范的Caliburn方法在TryClose
上实施ShellViewModel
?
即我是否必须致电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
}
答案 0 :(得分:1)
从TryClose
ShellViewModel
方法调用每个子视图模型的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();
}
}
答案 1 :(得分:1)
好的,这是我最终提出的解决方案:
// 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);
}