从现有视图模型访问视图模型的正确方法

时间:2010-10-31 18:45:38

标签: c# wpf mvvm prism

我对MVVM有些新意。我不确定做我想做的最好的方法是什么。

以下是该方案:

我有一个将要显示另一个窗口的VM。我可以调用myNewWindowView.Show(),但首先我需要在新窗口的VM中设置一些数据。

我应该将myNewWindowViewNewWindowViewModel同时暴露给调用的ViewModel吗?

以下是一个例子:

class MainVM
{
    public void FindCustomer(string nameParial)
    {
       List<Customer> customers = ServiceCall.GetCustomers(nameParital);
       // This is the part I am not sure how to do.  I am not sure if this
       //  View Model should have a reference to a different view model and
       //  the view too.
       myNewWindowViewModel.CustomerList = customers;
       myNewWindowView.Show();
    }
}

2 个答案:

答案 0 :(得分:3)

我会将viewmodel与任何视图分开。我倾向于将它们视为层,但它们只能在一个方向上互换。

因此,foo类型的模型可以在其上层叠任何视图模型,并且它永远不会期望或关心viewmodel类型。

一个viewmodel只能用于一种类型的模型,但它并不关心或期望哪种类型的视图会使用它。

视图将针对特定类型的视图模型。

你似乎拥有的是一个关注视图正在做什么的视图模型,这对我来说似乎是错误的。

如果是我,我会看到MainVM的视图显示新窗口,让MainVM为新窗口传递适当的视图模型。

这是我将放在主视图模型

视图后面的代码
class MainWindow : Window
{
     public MainWindow()
     {
          Initialize();
          DataContext = new MainVM();
     }

     public void FindCustomerClick(object sender, RoutedEventArgs args)
     {
          CustomerListView clv = new CustomerListView();
          clv.DataContext = (DataContext as MainVM).FindCustomer(search.Text);
          clv.Show();
     }
}

如您所见,viewmodel有一个方法,它接受一个字符串并返回一个CustomerListViewModel,然后将其应用于CustomerListView的DataContext。

答案 1 :(得分:2)

不要在视图模型中引用视图。视图创建视图和视图模型创建视图模型。

实现这种关注点分离的一种简单方法是使用事件。快速而肮脏的方法是在父视图模型上创建ChildViewModel属性,然后在视图中处理PropertyChanged,例如:

ParentViewModel vm = (ParentViewModel)DataContext;
vm.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "ChildViewModel")
    {
        MyChildWindow w = new MyChildWindow();
        w.Show(vm.ChildViewModel);
    }
};

现在每次父视图模型更改ChildViewModel属性时,父视图将打开一个新的子视图。

一种不那么快速且不那么脏的方法是创建一个CreateViewEventHandler委托和CreateViewEventArgs类,并使事件处理程序和受保护的OnCreateView方法成为您的基础的一部分查看模型类(假设您有一个)。这允许视图模型更加明确地表示何时应该创建子窗口。

请注意,如果父视图模型知道子视图模型何时关闭很重要,则子视图模型可以公开父可以订阅的事件(或者,再次使用属性和{{1事件)。

请注意,在这两种情况下,您都可以编写单元测试来验证视图模型是否在不涉及视图的情况下打开窗口(即引发事件)。

我自己没有使用过任何MVVM框架,但是我所看到的那些框架具有旨在促进此类事情的消息传递工具。