开发者

Caliburn bug with Show.Busy() and Show.NotBusy()

I have a dialog that is displayed with Show.Dialog(), and has these steps in a method attached to the Loaded event of the view:

  1. Show.Busy()
  2. Possible long-running web request (I have a custom asynchronous IResult here)
  3. Popup if error via Show.MessageBox()
  4. Show.NotBusy()

I have found if you close my view at step 2 when it is taking a while, and re-open, the busy indicator for step 1 on the new view isn't displayed.

So at first, I thought it was my fault, and put a simple mechanism to cancel step 4 if the view was closed. But no luck...

From what it looks like, Show.Busy() in step 1 is attempting to interact with the view that was already closed. Is this a bug in Caliburn?

My ViewModel is a singleton, so that could also attribute to the issue I suppose. For a test, I switched to a IsBusy boolean property and the problem goes away. However this would be a large change to make throughout my entire application.

Thoughts on any workarounds? Or can one of the Caliburn guys help me out here? I am using the latest release of the full version of Caliburn.

UPDATE:

I tried Marco's workaround, imported IBusyService and did this in my ViewModel:

public override void TryClose(bool? dialogRe开发者_运维技巧sult)
{
    _busyService.MarkAsNotBusy(this);

    base.TryClose(dialogResult);
}

But it doesn't seem to help. Would it help if I made a simple repro?

UPDATE #2:

I went ahead and made a repro, since that alot of the time will identify issues.

Turns out, it is related to me having to directly call the IWindowManager. My application is partially WinForms with a plugin architecture, and we use several Caliburn-based plugins.

Here is an example of the code causing the issue:

    if (_child.IsActive)
    {
        _child.BringToFront();
    }
    else
    {
        _manager.ShowWindow(_child);
    }

This is in the click event handler of a WinForms NotifyIcon MenuItem.

_child is a Screen, where BringToFront() is calls the Activate method of the underlying View (by a service, of course). _manager is the IWindowManager.

If you are running straight Caliburn, Show.Dialog() does not cause the issue.

Any ideas on a workaround? I'm not sure this is a Caliburn issue anymore, but possibly just caused by the direct use of IWindowManager.


The busy VMs (and related busy indicator UIElement) are kept in a registry into DefaultBusyService.
My guess is that when the VM is closed before being marked as not busy, the related entry is kept in the registry, thus preventing the service to work on the newer UIElement when the same VM instance is shown again.

I should investigate a little more, though; I filed an issue: http://caliburn.codeplex.com/workitem/8395

As a temporary workaround you might try calling IBusyService.MarkAsNotBusy on the VM shutdown phase, passing the reference of the VM itself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜