Caliburn Micro: убедитесь, что все OnDeactivates были вызваны до закрытия приложения - PullRequest
0 голосов
/ 17 мая 2018

У меня есть приложение 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);
}

Когда приложение закрывается, оно вызывает OnDeactivate только на 1 или 2 виртуальных машинах, затем приложение закрывается.
Как гарантировать, что OnDeactivate будет вызываться на всех виртуальных машинах перед закрытием приложения?
Я попытался добавить Sleep в TryClose, и это не сработало.

А также: существует ли канонический способ 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 голосов
/ 18 мая 2018

Хорошо, вот решение, которое я наконец-то придумала:

// ShellViewModel
public override void TryClose(bool? dialogResult = default(bool?))
{
    _disposeList.Dispose();

    while (Items.Any())
       DeactivateItem(Items.First(), true);

    base.TryClose(dialogResult);
    Application.Current.Shutdown();
}

И переопределить OnDeactivate в каждой отдельной виртуальной машине:

protected override void OnDeactivate(bool close)
{
    _disposeList.Dispose();
    base.OnDeactivate(close);
}
0 голосов
/ 18 мая 2018

Вызовите метод 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();
    }
}
...