【问题标题】:Childwindows in MVVMMVVM 中的子窗口
【发布时间】:2010-06-17 10:59:10
【问题描述】:

我在理解有关 MVVM 的某些内容时遇到了问题。我的应用程序依赖于对话来处理某些事情。问题是,这些子窗口应该从哪里来?根据 MVVM,视图模型应该只包含业务逻辑并且对 UI 的实际知识为零。但是,考虑到它们是 UI 元素,我应该从其他什么地方调用我的 childwindows?

这不会造成元素之间的紧密耦合吗?

【问题讨论】:

    标签: c# wpf silverlight mvvm prism


    【解决方案1】:

    由于您使用 Prism 标记了问题,我将建议我过去使用 Prism 的方式。将 IEventAggregator 注入到您的 ViewModel 中,然后当您想要弹出对话框时,发布“ShowDialogEvent”或类似的东西。然后,有另一个名为“DialogModule”的模块或其他模块,它在初始化时订阅该事件,并显示对话框。此外,如果您想将数据传递回原始 ViewModel,请让对话框的 ViewModel 发布一个“DialogCloseEvent”或类似的内容,其中包含您需要的数据的有效负载。然后,您可以在主 ViewModel 中订阅该事件。

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      过去,我通过使用 Unity 解析具有Show() 方法和完成事件的自定义接口来实现此目的。然后在 ViewModel 中我会调用IScreen screen = container.Resolve<IScreen>(Resources.EditorWindowKey);,然后只需调用screen.Show();。

      这样做的最大好处是我可以在测试我的虚拟机时简单地更改我的 Unity 配置以删除视图。

      【讨论】:

        【解决方案4】:

        我一直用来执行此操作的主要途径是在您的视图层中创建一个命令。该命令对象接受一个参数,即您要显示的 ViewModel 对象。该命令然后找到适当的 ChildWindow,创建它并使用参数集作为内容显示它,或者您将设置它。这样,您只需将按钮的命令属性绑定到该命令,并将其命令参数绑定到要在弹出窗口中显示的对象,并且您的 ViewModel 对象不必关心它是如何显示的。

        提示用户输入(如保存脏文件或其他内容)在此方案中不起作用。但是对于您操作一些数据然后继续前进的简单弹出窗口,这非常有效。

        【讨论】:

          【解决方案5】:

          WPF Application Framework (WAF) 的 ViewModel 示例应用程序演示了如何显示 模态对话框。

          【讨论】:

            【解决方案6】:

            我建议在这种情况下使用控制器,例如 DI'ed dialogController 使用对话框外壳备份。源视图模型(即打开对话框的请求的来源)将调用dialogController.ShowDialog(<<ViewNameToHostInRegion>>,<<RegionName>>)。

            为了在对话框和源视图之间传输数据,您可以使用 MessageBus。因此,本质上,当您调用 ShowDialog() 时,您会填充消息总线,并且当调用目标视图(Dialog shell 中托管的视图)的关闭命令时——比如在“选择”按钮中——让目标视图添加/更新消息总线。这样源视图模型就可以处理更新的数据。

            它有很多优点:

            1) 您的源视图与作为 BlackBox 的对话框控制器一起使用。即它不知道对话框视图到底在做什么。

            2) 视图托管在 Dialog Shell 中——因此您可以一次又一次地重复使用该对话框

            3) 源视图的单元测试仅限于测试当前视图模型的实际功能,而不是测试对话框视图\视图模型。

            我遇到的一个提示是,在创建测试用例时,您可能需要编写可测试的对话框控制器,该控制器在运行测试用例时不会显示实际对话框。因此,您需要编写一个 TestableDialogController,其中 ShowDialog 什么都不做(除了从 IDialogController 派生并提供 ShowDialog() 的空白实现。

            以下是伪代码:

            LocalMessageBus.AddMessage(<MessageKey>,<MessageActualContentAsObject>);
            dialogController.ShowDialog(<TargetViewName_SayEmployeeList>);
            Employee selectedEmployee = LocalMessageBus.GetMessage(<MessageKey>) as Employee;
            if (selectedEmployee != null)
            {
            //doSomework with selected employee
            }
            

            【讨论】:

              猜你喜欢
              • 2010-10-20
              • 1970-01-01
              • 1970-01-01
              • 2015-04-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多