Caliburn Micro:确保在应用程序关闭之前调用所有OnDeactivate

时间:2018-05-16 21:32:16

标签: c# wpf caliburn.micro dispose application-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,然后应用关闭 如何保证在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
    }

2 个答案:

答案 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);
}