我有一个父导体。我想在里面显示第一个视图模型。然后在第一个视图关闭后(即完成一些操作),我想显示一个不同的视图模型。
我用的是Caliburn.Micro。贡献,其中传导结果在导体中显示子VM。它有一个很酷的扩展方法AfterClosingDo,它在子进程停用并关闭后运行一个协程。
然而,当我使用AfterClosingDo
运行另一个传导结果时,基本上会发生这种情况:
- 第一个子虚拟机已关闭
- 去激活事件发生,关闭操作后运行传导结果
- 在关闭后,我在父导体中使用传导结果打开第二个子VM
- 第二个子VM被正确激活 然而,
- 第一个子VM的去激活仍然没有完成,并且null项在导体 中被设置为活动。
第一个VM基本显示加载操作的进度,第二个VM显示实际数据。加载完成后,我想在父Conductor中显示数据(当然,使用第二个VM)。
所以,我的问题:在Caliburn.Micro
中是否有一种干净的方法来做到这一点,最好是不重写导体,屏幕等的默认行为。
我正在考虑使用EventAggregator,虽然我不确定,如果它是最好的解决方案。
我有一个非常类似的问题,我有一个导体打开一个子VM,然后一个确认框会弹出说"你想要关闭",并为原始项目CanClose
方法触发了一个回调,该方法具有与您描述的相同的效果。
弹出式虚拟机将关闭,但在关闭时它将触发一个回调,该回调应该关闭第一个虚拟机。
我的指挥最后重新激活了原来的VM,这很烦人。事件发生的顺序为:
- 打开VM 1
- 尝试关闭虚拟机1
- 关闭保护方法被触发
- 在关闭vm1时弹出vm2(使用相同的导体)
- VM 2上的确认按钮被点击
- 确认按钮触发关闭回调并关闭VM1
- VM2关闭
- 导体记得vm1在vm2之前是活动的,所以在vm1关闭后重新打开它
最后,我只是实现了一个接口,在关闭后触发。
关闭后有工作要做的子项目实现接口(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异常。
我找不到任何其他方法来做到这一点,因为最后一个触发的事件似乎是停用事件,它们仍然太早。