Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# M-V-VM设计问题。从ViewModel调用视图_C#_Wpf_Mvvm - Fatal编程技术网

C# M-V-VM设计问题。从ViewModel调用视图

C# M-V-VM设计问题。从ViewModel调用视图,c#,wpf,mvvm,C#,Wpf,Mvvm,我刚刚开始研究WPF应用程序的M-V-VM。到目前为止,除了这个特别的问题,一切都是有意义的 我有一个叫搜索的视图模型。此ViewModel绑定到datagrid并列出项的结果。现在,我有一个命令需要打开另一个视图,即项目的详细信息 在搜索视图中显示另一个视图的逻辑似乎不正确,根本不可测试 这是我的ViewModel实现,它是不可测试的 public class SearchViewModel { public void SelectItem() { // I want t

我刚刚开始研究WPF应用程序的M-V-VM。到目前为止,除了这个特别的问题,一切都是有意义的

我有一个叫搜索的视图模型。此ViewModel绑定到datagrid并列出项的结果。现在,我有一个命令需要打开另一个视图,即项目的详细信息

在搜索视图中显示另一个视图的逻辑似乎不正确,根本不可测试

这是我的ViewModel实现,它是不可测试的

public class SearchViewModel
{
   public void SelectItem()
   {
     // I want to call the DetailsView from here
     // this seems wrong, and is untestable
     var detailsView = new DetailsView();
     detailsView.Show();
   }
}

在该模式中,从ViewModel方法显示视图的逻辑在哪里?

我们在该模式上使用了一个变量,这里我们有表示VM的控制器,因此视图的datacontext是VM,DTO是VM/控制器的属性。我们仍然称它为控制器,因为我们使用它作为控制点,从而从视图中处理某些命令。(我认为)这是我们实现像您这样的命令的地方。

视图永远不应该在UI层“下面”的任何地方实例化。VM存在于该领域之下,因此这里不是放置该逻辑的地方(正如您已经意识到的)

几乎总会有一些UI级别的事件指示需要创建视图。在您的示例中,它可能是datagrid上的一个行(双击)事件。这将是一个新的地方,显示您的详细信息查看窗口。

正如基夫所说:


视图不应在UI层“下方”的任何位置实例化。VM存在于该领域之下,因此这里不是放置该逻辑的地方(正如您已经意识到的)

几乎总是会有一些用户界面 级别事件,该事件将指示 需要创建视图。在你的 例如,它可能是一行(双精度) 单击datagrid上的事件。那个 将是一个展示新事物的地方 您的详细信息查看窗口

您必须认识到,M-V-VM与其他模式(如MVC或MVP)略有不同。ViewModel不直接了解UI。打开另一个视图是视图特有的功能。视图模型应该不太关心使用其数据的视图是什么或有多少视图。我很可能永远不会通过命令打开视图


这是一条基本的经验法则

  • 如果您正在处理中的本地操作 你的观点,你可以从 视图模型

  • 如果是交叉视图(比如显示搜索屏幕),那么要么使用EventAggregator模式(事件服务),要么插入一个应用程序控制器,在该控制器上调用方法,然后它依次显示搜索


包括一种使用
iVisualizerService
的方法。此接口定义了一个UI控制器,可用于从ViewModel以模态或无模态形式显示对话框。基本上,在父vm中,您创建的viewmodel应该位于新视图之后,服务会找到关联的视图(基于某种约定或注册),然后显示它。

感谢您的帮助,这似乎是一个可行的解决方案。尽管我不能对设置视图的逻辑进行单元测试(设置与注入的ViewModel交互的属性),但它会让ViewModels保持可测试性,这是大多数逻辑所在。如果一个简单的事件打开视图,这是好的。但是,如果事件需要更多的操作、数据获取和验证,该怎么办呢。你能把这些东西也放到视野里吗?或者创造另一个间接层次?确实如此。和萨姆在这里问的问题一样。如果在打开视图之前需要更多数据或逻辑,该怎么办?(例如,如果属性x=1打开视图1,如果属性x=2打开其他视图)@Sam@Tom:事件的参数将从UI传递所需的任何数据。然后,处理程序使用该数据做出决策,和/或检索更多数据。我喜欢将我的事件处理程序放在控制器上,以使我的虚拟机尽可能轻。请看一下Prism 2.0中的事件聚合和命令模式,以获得一个很好的示例。它实际上展示了几种不同的方法。