1

我有一个使用 Show.Dialog() 显示的对话框,并且在附加到视图的 Loaded 事件的方法中具有这些步骤:

  1. Show.Busy()
  2. 可能长时间运行的 Web 请求(我在这里有一个自定义的异步 IResult)
  3. 如果通过 Show.MessageBox() 出错则弹出
  4. Show.NotBusy()

我发现如果您在第 2 步关闭我的视图需要一段时间,然后重新打开,则不会显示新视图上第 1 步的忙碌指示符。

所以一开始,我以为是我的错,如果视图被关闭,我就放了一个简单的机制来取消第 4 步。但没有运气...

从它的样子来看,第 1 步中的 Show.Busy() 正在尝试与已经关闭的视图进行交互。这是 Caliburn 中的错误吗?

我的 ViewModel 是一个单例,所以这也可能归因于我认为的问题。对于测试,我切换到 IsBusy 布尔属性,问题就消失了。然而,在我的整个应用程序中,这将是一个很大的改变。

对任何解决方法的想法?或者其中一个 Caliburn 人可以在这里帮助我吗?我正在使用最新版本的完整版 Caliburn。

更新:

我尝试了 Marco 的解决方法,导入 IBusyService 并在我的 ViewModel 中执行此操作:

public override void TryClose(bool? dialogResult)
{
    _busyService.MarkAsNotBusy(this);

    base.TryClose(dialogResult);
}

但这似乎没有帮助。如果我做一个简单的复制会有帮助吗?

更新#2:

我继续进行了复制,因为很多时候会发现问题。

原来,这与我必须直接调用 IWindowManager 有关。我的应用程序部分是带有插件架构的 WinForms,我们使用了几个基于 Caliburn 的插件。

以下是导致问题的代码示例:

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

这是在 WinForms NotifyIcon MenuItem 的单击事件处理程序中。

_child 是一个 Screen,BringToFront() 调用底层 View 的 Activate 方法(当然是通过服务)。_manager 是 IWindowManager。

如果您直接运行 Caliburn,则 Show.Dialog() 不会导致问题。

关于解决方法的任何想法?我不确定这是否是 Caliburn 问题,但可能只是由直接使用 IWindowManager 引起的。

4

1 回答 1

2

繁忙的 VM(和相关的繁忙指示器 UIElement)保存在 DefaultBusyService 的注册表中。
我的猜测是,当虚拟机在被标记为不忙之前关闭时,相关条目会保留在注册表中,从而在再次显示相同的虚拟机实例时阻止服务在较新的 UIElement 上工作。

不过,我应该进行更多调查;我提出了一个问题:http ://caliburn.codeplex.com/workitem/8395

作为临时解决方法,您可以尝试IBusyService.MarkAsNotBusy在 VM 关闭阶段调用,传递 VM 本身的引用。

于 2011-03-10T23:41:14.483 回答