Show one child VM, then show another, after the first was closed

核能气质少年 提交于 2019-12-12 20:24:00

问题


I have one parent conductor. I want to show first view-model inside it. Then after first one is closed (i.e. some operation is done), I want to show a different view-model.

I'm using Caliburn.Micro.Contrib, where a ConductResult displays child VM in a Conductor. It has a cool extension method AfterClosingDo, which runs a coroutine after that child was deactivated and closed.

However, when I run another ConductResult using AfterClosingDo, basically this happens:

  • first child VM is closed
  • Deactivated event occurs, ConductResult runs AfterClosing action
  • in AfterClosing, I open second child VM using ConductResult in parent Conductor
  • second child VM is properly activated
  • however, the deactivation of first child VM still isn't completed, and null item is set as active in the Conductor

First VM basically shows progress of a load operation, second VM shows actual data. After the load is complete, I want to show the data in parent Conductor (using second VM, of course).

So, my question: is there a clean way to do this in Caliburn.Micro, preferably by not overriding default behavior of Conductor, Screen, etc.

I was thinking of using EventAggregator, though I'm not sure, if it's the best solution.


回答1:


I had a very similar issue where I had a conductor opening a child VM, then a confirmation box would pop-up saying "do you want to close" and had fired a callback for the original items CanClose method which had the same sort of effect as you described.

The popup VM would close, but in closing it would fire a callback which was supposed to close the first VM.

My conductor ended up re-activating the original VM which was annoying. The order of events was:

  • Open VM 1
  • Try Close VM 1
  • CanClose guard method fired
  • Popup VM 2 (using same conductor) in CanClose of VM 1
  • Confirm button on VM 2 is clicked
  • Confirm button fires callback for CanClose and closes VM1
  • VM2 Closes
  • Conductor remembers that VM 1 was active before VM 2 so re-opens VM 1 after it's closed

In the end I just implemented an interface which fired after the close.

Child items which have work to do after they have closed implement the interface (IAfterClose)

Then I provided an override for DeactivateItem on the conductor:

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

        base.DeactivateItem(item, close);

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

This made sure that the callback wasn't fired too early. Not sure if this will benefit you (since I've not used the contrib library) but it might give you some ideas.

The only downside to this was that I had to make a fix to DefaultCloseStrategy as when the callback would fire it would throw a null reference exception in there. The fix I applied seemed to cause no ill-effect but I've not really looked at why the null ref exception was thrown.

I couldn't find any other way to do this since the last event that fires seems to be the deactivation events and they are still to early.



来源:https://stackoverflow.com/questions/15465419/show-one-child-vm-then-show-another-after-the-first-was-closed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!