我在理解MVVM方面遇到了问题。我的应用程序依赖于某些事物的对话框。问题是,这些儿童窗口应该从哪里来?根据MVVM,viewmodels应该只包含businesslogic,并且对UI没有实际知识。但是,考虑到它们是UI元素,我应该将其他地方称为我的childwindows?
这不会在元素之间产生紧密耦合吗?
答案 0 :(得分:1)
既然你用Prism标记了这个问题,我会建议我过去使用Prism的方式。将IEventAggregator注入到您的ViewModel中,然后当您想要弹出对话框时,发布一个“ShowDialogEvent”或类似的东西。然后,让另一个名为“DialogModule”的模块或其他任何模块在初始化时订阅该事件,并显示该对话框。此外,如果要将数据传递回原始ViewModel,请让对话框的ViewModel发布一个“DialogCloseEvent”或类似的东西,其中包含您需要的数据的有效负载。然后,您可以在主ViewModel中订阅该事件。
答案 1 :(得分:0)
答案 2 :(得分:0)
过去,我通过使用Unity解析具有Show()
方法和已完成事件的自定义界面来完成此操作。然后在ViewModel中,我会调用IScreen screen = container.Resolve<IScreen>(Resources.EditorWindowKey);
,然后只需调用screen.Show();
。
这样做的一大优点是,我可以在我测试VM的时候只需更改Unity配置即可删除视图。
答案 3 :(得分:0)
我一直用来做这个的主要途径是在View层中创建一个命令。该命令对象接受一个参数,该参数是您要显示的ViewModel对象。然后该命令找到相应的ChildWindow,创建它并将参数设置为内容显示它,或者您将设置它。这样您就可以将按钮的命令属性绑定到该命令,并将其命令参数绑定到要在弹出窗口中显示的对象,而ViewModel对象永远不必关心它是如何显示的。
提示用户输入(如保存脏文件或其他内容)在此方案中不起作用。但是对于简单的弹出窗口,你操作一些数据然后继续前进,这非常有用。
答案 4 :(得分:0)
WPF Application Framework (WAF) 的ViewModel示例应用程序演示了如何显示模态对话框。
答案 5 :(得分:0)
我建议在这种情况下使用控制器,比如DI'ed dialogController备份了一个对话框shell。源视图模型(即打开对话框的请求所在的位置)将调用dialogController.ShowDialog(<<ViewNameToHostInRegion>>,<<RegionName>>)
。
为了在对话框和源视图中传输数据,您可以使用MessageBus。所以基本上当你调用ShowDialog()时,你会填充消息总线,并且当目标视图的关闭命令(在Dialog shell中托管的视图)被调用时 - 例如在“选择”按钮中 - 让目标视图添加/更新消息总线。因此,源视图模型可以使用更新的数据。
它有很多优点:
1)您的源视图使用对话框控制器作为BlackBox。即它不知道Dialog视图究竟在做什么。
2)视图托管在Dialog Shell中 - 因此您可以反复重复使用该对话框
3)源视图的单元测试仅限于测试当前视图模型的实际功能,而不是测试对话视图\视图模型。
我遇到的这个问题是,在创建测试用例时,您可能需要编写可测试的Dialog控制器,它在运行测试用例时不会显示实际的对话框。因此,您需要编写一个TestDialogController,其中ShowDialog不执行任何操作(除了从IDialogController派生并提供ShowDialog()的空白实现。
以下是psudeo代码:
LocalMessageBus.AddMessage(<MessageKey>,<MessageActualContentAsObject>);
dialogController.ShowDialog(<TargetViewName_SayEmployeeList>);
Employee selectedEmployee = LocalMessageBus.GetMessage(<MessageKey>) as Employee;
if (selectedEmployee != null)
{
//doSomework with selected employee
}