使用WPF MVVM模式打开新窗口的最佳实践

时间:2010-11-24 11:25:50

标签: wpf mvvm

我一直在想这个问题......从另一个视图模型打开一个新窗口(view& viewmodel)的最佳做法是什么如果我们记住打开新窗口的viewmodel不知道该视图的存在(应该如此)。

感谢。

5 个答案:

答案 0 :(得分:13)

我更喜欢使用通过ViewModel构造函数插入的动作委托。这也意味着我们可以在单元测试期间轻松验证:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new MainViewModel(() => (new Window()).Show()); // would be actual window
    }
}

public class MainViewModel
{
    private Action popupAction;
    public MainViewModel(Action popupAction)
    {
        this.popupAction = popupAction;
    }

    public ICommand PopupCommand { get; set; }

    public void PopupCommandAction()
    {
        popupAction();
    }
}

public class SomeUnitTest
{
    public void TestVM()
    {
        var vm = new MainViewModel(() => { });
    }
}

答案 1 :(得分:5)

我不使用ViewModel打开另一个View / ViewModel。这由财务主任负责。 ViewModel可以通知Controller(例如,通过Event)用户期望看到下一个View。 Controller在IoC Container的帮助下创建View / ViewModel。

WPF Application Framework (WAF) 的ViewModel(EmailClient)示例应用程序中显示了它的工作原理。

答案 2 :(得分:3)

使用介体模式,例如mvvmlight的messenger类:

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338

基本思想是viewmodel向其视图发送消息。然后接收视图如下所示:

OnMsgRecived() {

  Viewmodel vm = New Viewmodel() - Or use dependency injection to resolve

  View v = new View()
  v.DataContext = vm
  v.Show()
}

这允许发送消息的视图模型显示另一个窗口,其中没有“知道”如何或谁进行了打开。

答案 3 :(得分:2)

我个人更喜欢在我的ViewModel中引发事件,以向视图发出信号,告知它需要执行类似打开窗口的操作。我尽量不直接这样做,所以我在ViewModel中看不到像OpenWindow这样的事件,因为在我看来,这似乎违反了View和ViewModel之间的区别。相反,我可能会做一个属性改变状态并相应地引发一个PropertyChanged事件,视图可以监听,然后决定打开一个窗口来响应这个信号。在某些情况下,窗口的打开根本与ViewModel中的某些内容无关,而只是View的一个功能。在这些情况下,我根本不害怕在View的代码隐藏部分中放置代码来打开另一个视图。

mediator pattern只是使它更加松散耦合,并允许主应用程序窗口View或高度嵌套的View可以在应用程序内全局侦听消息,而无需直接访问ViewModel以附加事件处理程序等等。要过滤掉不相关的消息,您可以查看某种消息源值或消息源自何处的其他指示。对于那些熟悉Windows消息的人以及在非托管和WinForms开发中如何在不同控件(Windows)之间工作的人来说,可能是一种理解系统的方法,可以在广播消息的中介之上构建。

答案 4 :(得分:0)

我同意类似中介的方法,但OnMsgReceived在视图的代码隐藏中清楚地处理,是否有一种避免这种情况的好方法?