Wpf 是否允许ViewModel关闭窗口?

Wpf 是否允许ViewModel关闭窗口?,wpf,mvvm,design-patterns,Wpf,Mvvm,Design Patterns,最近,我回答了一个问题,我认为这是一个MVVM解决方案。请不要把重点放在实际问题上,因为这并不是困扰我的问题。在这种情况下,我甚至不会在那里使用我的解决方案。我肯定会使用@ChrisW的解决方案 然后@SpikeX的回应出现了,现在我感到困惑。但我必须为此感谢他。我不能停止思考这个问题,因为直到现在我可能对MVVM的想法是错误的 于是我开始研究: 等等 正如您所看到的,我不是宇宙中唯一一个从ViewModel关闭窗口的人。但我真的能做到吗?或者我真的不应该在ViewModel中使用windo

最近,我回答了一个问题,我认为这是一个MVVM解决方案。请不要把重点放在实际问题上,因为这并不是困扰我的问题。在这种情况下,我甚至不会在那里使用我的解决方案。我肯定会使用@ChrisW的解决方案

然后@SpikeX的回应出现了,现在我感到困惑。但我必须为此感谢他。我不能停止思考这个问题,因为直到现在我可能对MVVM的想法是错误的

于是我开始研究:

等等


正如您所看到的,我不是宇宙中唯一一个从
ViewModel
关闭窗口的人。但我真的能做到吗?或者我真的不应该在
ViewModel
中使用window吗。MVVM真的这么严格吗?我的解决方案真的打破了MVVM模式吗

在我看来,viewmodel应该与使用它的客户端技术完全隔离

由于在实际的
窗口
实例上调用close方法,因此需要对特定于客户机的程序集(在本例中为WPF)进行引用,这几乎不可能将该viewmodel用于其他任何用途

如果您想同时创建WPF、Silverlight、Windows Phone、Windows应用商店应用程序等客户端,您就没有机会为它们使用相同的viewmodel,因为Windows Phone可能不知道WPF窗口是什么

此外,当您在其中引用实际视图元素时,单元测试viewmodels会变得更加麻烦

因此,您可以在某种视图适配器中将窗口抽象出来,而不是直接引用窗口

如果viewmodel只知道这样的界面:

public interface IView
{
    void Show();
    void Close();
}
…您的每个客户端都可以创建自己的实现,并将其注入到viewmodel中,以便它在任何给定的客户端上执行正确的操作


关键是viewmodel不了解实际视图。所有东西都隐藏在接口的实现中。

是的,您的解决方案打破了这种模式。最大的缺点是,您无法完全测试VM和逻辑,这会干扰窗口的关闭。但是,如果你需要努力实现一个解决方案,你必须考虑到。p> 因此,如果你真的想坚持使用MVVM,你可以使用我在第一个链接中发布的解决方案。我在这里复制了我帖子的重要部分

引用

<Window x:Class="AC.Frontend.Controls.DialogControl.Dialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:DialogControl="clr-namespace:AC.Frontend.Controls.DialogControl" 
        xmlns:hlp="clr-namespace:AC.Frontend.Helper"
        MinHeight="150" MinWidth="300" ResizeMode="NoResize" SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen" Title="{Binding Title}"
        hlp:AttachedProperties.DialogResult="{Binding DialogResult}" WindowStyle="ToolWindow" ShowInTaskbar="True"
        Language="{Binding UiCulture, Source={StaticResource Strings}}">
        <!-- A lot more stuff here -->
</Window>
/Quote

<Window x:Class="AC.Frontend.Controls.DialogControl.Dialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:DialogControl="clr-namespace:AC.Frontend.Controls.DialogControl" 
        xmlns:hlp="clr-namespace:AC.Frontend.Helper"
        MinHeight="150" MinWidth="300" ResizeMode="NoResize" SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen" Title="{Binding Title}"
        hlp:AttachedProperties.DialogResult="{Binding DialogResult}" WindowStyle="ToolWindow" ShowInTaskbar="True"
        Language="{Binding UiCulture, Source={StaticResource Strings}}">
        <!-- A lot more stuff here -->
</Window>
您唯一需要的就是这样一个
VM
,以使我的解决方案工作

公共类WindowVm:ViewModelBase//实现INotifyPropertyChanged的基类
{
私有布尔?\u对话框结果;
公共布尔?对话结果
{
获取{return\u dialogResult;}
设置
{
_对话框结果=值;
RaisePropertyChanged(()=>DialogResult);
}
}
//…许多其他财产
}