WPF:从MVVM模型关闭窗口

22 浏览
0 Comments

WPF:从MVVM模型关闭窗口

在MVVM模式中,我试图从ViewModel中关闭一个窗口。我尝试使用以下方法获取窗口:

Window parentWindow = Window.GetWindow(this);

但是我无法实现这个,我应该如何获取ViewModel的窗口,以便能够关闭窗口?我希望能够在代码中实现这个功能。

你能在代码中找到父窗口吗?

0
0 Comments

问题的原因是在MVVM模式中,ViewModel无法直接关闭窗口,因为ViewModel和View之间没有直接的联系。解决方法是让ViewModel来关闭窗口,通过在ViewModel中传递信息给Model,然后判断是否有有效数据,如果没有则关闭窗口。在MVVM中,一个空的View表示没有数据的正常方式。如果需要在ViewModel中关闭窗口,可以参考这篇文章:asimsajjad.blogspot.de/2010/10/…

0
0 Comments

问题:WPF中,如何从Model MVVM中关闭一个Window?

原因:在View Model中引用View不是最佳实践。因为当你对View Model进行单元测试时,需要实例化View。对于小的View来说,这可能不难,但是对于具有复杂依赖树的复杂View来说,这并不好。

解决方法:我个人认为,与View进行通信的最简单方法是通过在ViewModel构造函数中传递IInputElement。IInputElement的好处是它具有路由事件的支持,它具有RaiseEvent和AddHandler方法,用于路由事件。因此,您可以自由地将事件冒泡/隧道/直接传递给应用程序中的任何View或ViewModel,而无需使用任何附加库。

以下是我在ViewModel中的简化代码,但请记住,这种技术只适用于View First的方法:

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));
    }
}

在您的View中简单地使用以下代码:

DataContext = new MyViewModel(this);
//注意构造函数中的"this"

在您应用程序的根视图(Window)中简单地使用以下代码:

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这样的模拟库。

进一步阅读,您可以了解如何使用Routed Event。

0
0 Comments

WPF中的MVVM模式中,ViewModels不应该以任何方式引用View,包括关闭窗口。相反,View和ViewModel之间的通信通常通过某种事件或消息系统进行,例如Microsoft Prism的EventAggregator或MVVM Light的Messenger。

例如,View应该订阅监听CloseWindow类型的事件消息,当接收到这样的消息时,View应该关闭自己。然后,ViewModel只需要在想要告诉View关闭时广播一个CloseWindow消息。

如果您感兴趣,我在我的博客文章《Communication between ViewModels》中对MVVM中的事件系统进行了简要概述,并提供了一些示例。

0