代码之家  ›  专栏  ›  技术社区  ›  Jens

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

  •  20
  • Jens  · 技术社区  · 14 年前

    我一直在想这件事。。。如果我们记住打开新窗口的View模型不知道该视图的存在(应该是),那么从另一个View模型中打开一个新窗口(视图和视图模型)的最佳实践是什么。

    谢谢。

    5 回复  |  直到 14 年前
        1
  •  5
  •   jbe    14 年前

    我不使用ViewModel打开另一个View/ViewModel。这是管制员的责任。ViewModel可以通知控制器(例如,通过事件)用户希望看到下一个视图。控制器在IoC容器的帮助下创建视图/视图模型。

    其工作原理显示在 WPF Application Framework (WAF) .

        2
  •  13
  •   Dean Chalk    14 年前

    我更喜欢使用通过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(() => { });
        }
    }
    
        3
  •  3
  •   dnndeveloper    14 年前

    使用中介模式,如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()
    }
    

    这允许发送消息的viewmodel显示另一个窗口,而不知道是如何打开的,也不知道是谁打开的。

        4
  •  2
  •   jpierson    14 年前

    我个人更喜欢在ViewModel中引发事件,以向视图发出信号,表明它需要执行诸如打开窗口之类的操作。不过,我尽量不直接这样做,这样就不会在ViewModel中看到类似OpenWindow的事件,因为在我看来,这似乎违反了视图和ViewModel之间的分隔。相反,我可能要做的是使用一个属性来更改状态,并相应地引发一个PropertyChanged事件,在该事件中,视图可以侦听,然后决定打开一个窗口来响应此信号。在某些情况下,窗口的打开与ViewModel中的某些内容完全不相关,只是视图的一个功能。在这些情况下,我一点也不怕在视图的代码隐藏部分中放置用于打开另一个视图的代码。

    这个 mediator pattern 只需使其更松散地耦合,并允许主应用程序窗口视图或高度嵌套的视图可以在应用程序中全局侦听消息,而无需直接访问ViewModels以附加事件处理程序等。若要筛选出不相关的消息,可以查看某种消息源值或消息来源的其他指示。对于那些熟悉Windows消息以及如何在非托管和WinForms开发中的不同控件(Windows)之间工作的人来说,理解系统可以建立在广播消息的中介之上。

        5
  •  0
  •   W1ck3dHcH    14 年前

    我同意类似中介的方法,但是OnMsgReceived显然是在视图的代码背后处理的,有没有好的方法来避免这种情况?