显示一个子VM,然后在第一个关闭后显示另一个

时间:2013-03-17 19:50:29

标签: c# mvvm viewmodel caliburn.micro

我有一位家长。我想在其中显示第一个视图模型。然后在第一个关闭之后(即完成一些操作),我想展示一个不同的视图模型。

我正在使用Caliburn.Micro.Contrib,其中 ConductResult 指挥中显示子VM。它有一个很酷的扩展方法 AfterClosingDo ,在该子项被停用并关闭后运行一个协程。

但是,当我使用AfterClosingDo运行另一个ConductResult时,基本上会发生这种情况:

  • 第一个子VM已关闭
  • 发生停用事件,ConductResult运行AfterClosing操作
  • 在AfterClosing中,我使用父导体
  • 中的ConductResult打开第二个子VM
  • 第二个子VM已正确激活
  • 但是,第一个子VM的停用仍未完成, null 项目在Conductor中设置为活动

第一个VM基本上显示了加载操作的进度,第二个VM显示了实际数据。加载完成后,我想在父Conductor中显示数据(当然使用第二个VM)。

所以,我的问题是:在Caliburn.Micro中是否有一种干净的方法可以做到这一点,最好不要覆盖指挥,屏幕等的默认行为。

我正在考虑使用 EventAggregator ,虽然我不确定,但这是否是最佳解决方案。

1 个答案:

答案 0 :(得分:3)

我有一个非常类似的问题,我有一个指挥打开一个子VM,然后会弹出一个确认框说“你想要关闭”并且已经开始回调原始项CanClose方法它具有与你描述的相同的效果。

弹出VM将关闭,但在关闭时它将触发一个应该关闭第一个VM的回调。

我的指挥最终重新激活原来的VM,这很烦人。事件的顺序是:

  • 打开VM 1
  • 尝试关闭VM 1
  • CanClose guard method fired
  • VM 1的CanClose中的弹出VM 2(使用相同的导体)
  • 单击VM 2上的确认按钮
  • 确认按钮触发CanClose的回调并关闭VM1
  • VM2关闭
  • Conductor记得VM 1在VM 2之前处于活动状态,因此在关闭后重新打开VM 1

最后我刚刚实现了一个在关闭后触发的接口。

关闭后有工作要做的子项目实现界面(IAfterClose

然后我在指挥上为DeactivateItem提供了覆盖:

    public override void DeactivateItem(IScreen item, bool close)
    {
        var afterClose = item as IAfterClose;

        base.DeactivateItem(item, close);

        if (afterClose != null && close)
            afterClose.AfterClose();
    }

这确保了回调没有过早发布。不确定这是否会让你受益(因为我没有使用过contrib库),但它可能会给你一些想法。

唯一的缺点是我必须修复DefaultCloseStrategy,因为回调会触发它会在那里抛出一个空引用异常。我应用的修复似乎没有造成任何不良影响,但我还没有真正看到为什么抛出空引用异常。

我找不到任何其他方法来执行此操作,因为上一次触发的事件似乎是停用事件并且它们仍处于早期状态。