在Caliburn Micro中进行多个窗口的正确方法?

时间:2015-08-06 07:35:32

标签: c# wpf caliburn.micro

我正在使用Caliburn.Micro开发应用程序。我需要在多台显示器上同时打开一组相同的 windows ,我无法弄清楚如何干净利落地完成这项工作。

我的想法是:

  • ChildViewModel / ChildView包含我需要在多个屏幕上显示的内容。
  • ParentViewModel继承自ConductorBase<ChildViewModel>
  • 创建ParentViewModel后,会创建所需数量的ChildViewModel,并使用WindowManager.ShowWindow来显示每个WindowManager
  • 我的ParentView实现负责将这些视图放在它们应该的位置。

以上所有工作都有,但有一个例外:string path = @"c:/users/1/desktop/temp.txt" GrantAccess(path); 显示在自己的窗口中。我怎样才能避免这种情况发生?做我想做的事情的规范方式是什么?

我想要做的是从单个导体进行多个窗口,而导体本身没有显示窗口。

2 个答案:

答案 0 :(得分:6)

这个架构怎么样?

                          SystemTrayVM
      (VM for your notification area, its View is the sys tray icon)
                                |
                                |
                      MultipleDesktopManager
      (not a VM, not a ConductorBase, no View, not visible)
                                |
            .-------------------|------------------.
            |                   |                  |
            |                   |                  |
    SingleDesktopVM      SingleDesktopVM     SingleDesktopVM
(its View holds child views. If necessary, it can be a ConductorBase)
                                |
                  .-------------|------------.------ - - - .
                  |             |            |
                  |             |            |
         SideBarChildVM    MainChildVM   FooterChildVM
  • SystemTrayVM 负责通过通知区域提供的所有交互(右键菜单操作等)。它实际上不会打开/关闭用户可见的窗口,而是将这些命令转发到 MultipleDesktopManager

  • MultipleDesktopManager 不可见且不是VM。它的责任是例如需要时打开/关闭所有单个桌面父窗口。作为完全独立的窗户,不需要完整的导体。根据我的经验,它足以为它提供一个 IWindowManager ,以便它可以实际显示/关闭单个桌面父窗口。也许它也可以激活/停用它们,但不需要跟踪当前活动项目或类似的东西。

  • SingleDesktopVM 负责本身内部显示的所有子视图/ VM。因此,如果需要,这可能是指挥......这实际上取决于父级内部子视图的生命周期。例如。如果有一个命令栏和一个主要内容并且它们总是在那里,那么你可能会选择一个包含其他虚拟机的更简单的父虚拟机。

最近我们遇到过&amp;解决了WPF应用程序启动不可见的问题,只能在系统托盘中找到,并且能够显示/隐藏实际的主应用程序窗口。
在那种情况下,我们将隐藏/显示主应用程序窗口的任务卸载到SystemTrayVM调用的辅助类(而不是VM)。这相当于此模式中的 MultipleDesktopManager

关于仅从系统托盘开始的WPF应用程序,我们整理了一个PoC on GitHub,其中显示了如何将this WPF NotifyIcon控件与Caliburn.Micro ViewModel优先方法和DI通过Autofac完全集成。

编辑:基本原理是CM提供的现有导体实现似乎更适合持有其他子 windows 窗口。如果支架本身不可见,那么这些导体实施可能不是最佳选择。正如你在评论中所说,这就像需要指挥也是一个屏幕。 CM composition doc page关于“准导体”有一点有趣。最后, MultipleDesktopManager 的想法基本上是管理许多窗口的简单导体,没有实现 IConductor 接口,但仍使用 WindowManager 为了正确处理 SingleDesktopVMs 生命周期。

答案 1 :(得分:-1)

也许我错过了一些东西,但你可以根据你提供的信息做下面的事情

第1步。

  • 转到处理Menuclick
  • 的班级(VM)
  • 添加一个私有值ParentConductor,它会像ParentViewModel那样执行相同的操作(对每个子节点持有一个引用并在关闭时关闭所有子节点)

第2步。

  • 修改您的MenuclickClickCommand,以便每次点击发生后点击
  • int ParentConductor
  • 创建您的孩子并在您的ParentConductor
  • 中添加参考号
  • 使用Caliburn创建一个foreach child的窗口

现在你应该可以关闭所有Child的关闭。 没有必要创建ParentView,因为只要您的班级(VM),您的指挥就会生活。

您还可以添加一种方法,以便售票员可以在关闭他的孩子之后将他自己从班级中删除