WPF:关闭从型号MVVM一个窗口(WPF: Close a Window from Model M

2019-09-18 03:29发布

我试图关闭从视图模型的窗口。 我使用MVVM模式。 我已经累到让使用窗口;

Window parentWindow = Window.GetWindow(this);

但我不能这样做,我怎么得到视图模型的窗口,以便我能够关闭该窗口。 我希望能够在代码中做到这一点。

您可以在代码中的父窗口?

Answer 1:

ViewModels不应引用View以任何方式,包括关闭窗口,在MVVM。

相反,之间的交流ViewViewModel通过某种事件或消息系统的典型的做法,如微软棱镜的EventAggregator ,或MVVM光的Messenger

例如, View应订阅监听类型的事件消息CloseWindow ,当它接收到的消息,就应自行关闭。 然后ViewModel只是有广播CloseWindow它想要告诉的消息随时View关闭。

有一个在MVVM事件系统的简要概述,以及一些例子,在我的博客文章的ViewModels之间的交流 ,如果你有兴趣



Answer 2:

是在视图模型引用视图是不是最好的做法。 为什么? 因为当你单元测试你的视图模型则需要你实例化视图,为小视图将不难做到这一点,但是对于依赖复杂的树一个复杂的看法? 这不会是一件好事。

对我来说,最简单的方法做视通信是通过传递IInputElement上视图模型构造。 的bennefit IInputElement被路由事件骨干,它具有RaiseEventAddHandler用于路由事件所需的方法。 因此,你可以泡/隧道/直接事件没有任何附加库上免费应用程序的任何视图或视图模型。

这里是我的视图模型简化代码,但请记住这种技术只对视图第一种方法工作

public class MyViewModel : INotifyPropertyChanged
{
    public static readonly RoutedEvent RequestCloseEvent = EventManager.RegisterRoutedEvent("RequestClose",
        RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyViewModel));

    private IInputElement dispatcher;

    public MyViewModel(IInputElement dispatcher)
    {
        this.dispatcher = dispatcher;
    }

    public void CloseApplication()
    {
        dispatcher.RaiseEvent(new RoutedEventArgs(RequestCloseEvent));
    }
}

您只需查看

DataContext = new MyViewModel(this)
//notice "this" on the constructor

和你的应用程序的根视图(窗口)简单地

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        AddHandler(MyViewModel.RequestCloseEvent, new RoutedEventHandler(onRequestClose));
    }

    private void onRequestClose(object sender, RoutedEventArgs e)
    {
        if (MessageBox.Show("Are you sure you want to quit?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
        {
            Close();
        }
    }
}

因为IInputElement是接口而不是类,您可以轻松地创建一个模拟类的单元测试

var target = new MyViewModel(new DispatcherMock)

或者您也可以使用像RhinoMocks模拟库

进一步阅读,你可以了解更多有关如何使用路由事件



Answer 3:

Let the ViewModel do this, if really in need.

The Models says for example, that there are no longer valid data

pass that information to the ViewModel

the ViewModel recognizes, that it can no longer display anything

and then closes the window.

An empty view is the normal way of expressing that there are no more data



Answer 4:

您可以在视图模型定义操作

public Action CloseAction { get; set; }

然后,在你的窗口(例如在DataContextChanged仅),你可以设置这个动作:

((IClosable)viewModel.Content).CloseAction = () => System.Windows.Application.Current.Dispatcher.Invoke(Close());

那么,这一切是一个更大的依赖注入模式的一部分,但是基本原理是在这里......接下来,你中庸之道需要调用从虚拟机的操作。



Answer 5:

有这个任务,不打破MVVM,行为,与Expression Blend的3推出,允许查看挂接到视图模型中完全定义的命令一个有用的行为。

这种现象说明了一个简单的技术允许视图模型来管理模型 - 视图 - 视图模型应用的视图的closing事件。

这使您可以挂钩您的视图(用户控件)行为,将提供对控件的窗口控制,使视图模型来控制窗口是否能够通过标准的个ICommand关闭。

使用行为允许视图模型在MV-VM管理视图生命期

http://gallery.expression.microsoft.com/WindowCloseBehavior/



文章来源: WPF: Close a Window from Model MVVM
标签: c# .net wpf mvvm