2

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

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

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

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

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

所以,我的问题:有没有一种干净的方法可以做到这一点Caliburn.Micro,最好不要覆盖导体、屏幕等的默认行为。

我正在考虑使用EventAggregator,但我不确定它是否是最好的解决方案。

4

1 回答 1

3

我有一个非常相似的问题,我有一个指挥打开一个子虚拟机,然后会弹出一个确认框说“你想关闭吗”并为原始 itemsCanClose方法触发了一个回调,其效果与你描述的。

弹出虚拟机会关闭,但在关闭时会触发一个回调,该回调应该关闭第一个虚拟机。

我的指挥最终重新激活了令人讨厌的原始虚拟机。事件的顺序是:

  • 打开虚拟机 1
  • 尝试关闭 VM 1
  • CanClose 保护方法被触发
  • 在 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回调何时触发它会在那里抛出一个空引用异常。我应用的修复似乎没有造成不良影响,但我并没有真正研究为什么会引发 null ref 异常。

我找不到任何其他方法来做到这一点,因为最后一个触发的事件似乎是停用事件,而且它们还为时过早。

于 2013-03-17T21:07:11.650 回答