我最近开始学习wpf并尝试使用mvvm .
我的理解是,在mvvm中,视图或模型都不应该知道另一个存在 .
我要做的是在屏幕上显示客户列表 . 但是如果我对viewModel进行编码,如下所示 . 这与我在网上看到的许多例子类似,然后我最终得到了一些看起来像这样的代码
class Customer
{
public String Name {get;set;}
public String Address {get;set;} }
}
class MainWindowViewModel
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
public ObservableCollection<Customer> Customer
{
get {return customers;}
}
public MainWindowViewModel()
{
//cust1 and cust2 are Customer objets
customers.Add(cust1);
customers.Add(cust2);
}
}
现在,如果我创建了 MainWindowViewModel 的实例并将其设置为我的 MainWindowView (我的视图)的datacontext,并且我进一步将viewmodels Customers 属性绑定到listBox,那么视图将需要对包含我的模型的程序集的引用 .
所以我的问题是 .
1)在MVVM中添加对允许的模型程序集的引用,因为这意味着视图知道模型 .
2)更好的解决方案是将每个 Customer 对象包装在 CustomerViewModel 中,并让MainWindowViewModel包含 ObservableCollection of CustomerViewModel 而不是 ObservableCollection of Customer . 这会将模型与视图完全分开 .
5 回答
我不确定为什么你认为包含你的观点的项目需要引用你的模型项目?您的视图中没有任何内容直接引用您的模型 - XAML中的绑定表达式仅按名称链接,并且无论如何都链接到视图模型上的属性,而不是您的模型 .
如果您的视图需要比模型提供的更多数据,则在视图模型中包装模型是一个不错的选择,并且不希望更改模型 . 例如,您可能需要显示
User
类型的Age
,但User
只有DateOfBirth
属性 . 如果您不想更改模型,则使用Age
属性创建UserViewModel
将是一个不错的选择 .您的问题的答案:
参考模型的视图有什么不好?这在简化代码时绝对可以 . 反过来说(模型 - >视图)是不好的做法 .
当您没有特殊需要时,不需要在 CustomerViewModel 中包装每个 Customer 对象 . 我建议采用务实的方式并保持代码简单 .
您可能对 WPF Application Framework (WAF) 的示例应用程序感兴趣,该应用程序显示了您在此处描述的场景 .
我们通常会创建一个CustomerViewModel . 这是由我们的通用CollectionViewModelBase类强制执行的 . 这不确定用户界面使用的每个部分都是特别创建的以便显示,并且我们在模型中没有任何与UI相关的代码,这些代码通常是可序列化的POCO .
MVVM模式与任何其他MVx模式(MVC,MVP,...)类似,因为它鼓励关注点分离(SoC),从而提高代码的可维护性/可测试性 . 除了通常的SoC之外,MVVM还提供以下内容:
视图逻辑的单元测试;这是因为您将逻辑从视图移动到视图模型中,使您的视图尽可能愚蠢 .
开发人员 - 设计师工作流程;因为视图是'dumb',所以在没有背后的逻辑的情况下使用XAML更容易 .
关于可见性,即什么是可见的,严格如下:
换句话说,ViewModel可以看到Model,但Model看不到ViewModel . 同样,View可以看到ViewModel,但反之亦然 .
由于ViewModel没有对View的引用,因此它可以在没有任何视图组件的情况下执行代码,这将启用上面的(1) .
ViewModel的目的是“塑造”您的模型以更轻松地绑定到View . 如果您的View很简单,那么执行以下操作是完全可以接受的:
这仍然允许(1)单元测试,(2)开发人员 - 设计者工作流程 .
使用混合方法也很好,有时会将模型暴露给您的视图,有时将其包装在ViewModel中 . 例如:
http://www.scottlogic.co.uk/blog/colin/2009/08/the-mini-viewmodel-pattern/
请不要创建一堆样板的ViewModel代码,只是因为你认为你必须这样做!
您肯定希望仅在视图中包装您的模型,如下所示: