EF4 + MVVM - 如何在ViewModel中公开实体?

6
我曾尝试不同的Model-View-ViewModel实现方式,发现有一种情况让我不确定正确的处理方法。我知道MVVM的一个目标是将视图与应用程序逻辑解耦,以便在没有视图的情况下测试逻辑。将逻辑放在ViewModel中,而该ViewModel不依赖于View就可以解决这个问题。很好。如果Model能够以这样的方式与ViewModel解耦,以至于它可以被模拟,那就更好了。
所以我的问题是,ViewModel是否应该将Model与View解耦?换句话说,通过ViewModel向View公开EntityFramework实体是否可以呢?例如,假设视图中有一个组合框,用户可以选择地址的州。在AddressViewModel中,State应该作为实际的实体类型属性公开,还是应该作为StateViewModel公开?如果它应该作为StateViewModel类型属性,那么我不明白AddressViewModel.State setter中应如何管理底层模型(因为在属性中设置的是StateViewModel而不是State实体)。
在我看来,这可能两种方式都可以,但似乎从未直接向视图公开模型更加一致。你怎么看?
4个回答

4

你应该努力将模型与视图完全解耦,这应该是一个目标,你可能会实现它,也可能不会,但仍然应该是你的目标。

具体来说,你的问题涉及到一个常量列表(或多或少),这是一个简单的情况。如果我理解有误,请纠正我,但你可能有一个States表,每个州有一个code和一个name,然后你有另一个表,它有对前一个表的外键。

在这种情况下,最好在应用程序初始化期间加载和创建 StateViewModel 列表,然后在整个应用程序中处理外键值(即状态code),而不是使用 StateViewModel 对象本身。你应该使用的属性是 ComboBoxSelectedValueSelectedValuePath,示例:

<ComboBox ItemsSource="{x:Static StateViewModel.StaticList}"
          SelectedValue="{Binding StateForeignKey}"
          SelectedValuePath="code"
          DisplayMemberPath="name" />

这将使用已经关闭的上下文创建StateViewModel对象,填充ComboBox,但是将选定项的code属性传递到绑定字段StateForeignKey,此外,ComboBox将显示name属性,以便人们可以读懂。

2
视图模型的目的是将视图与数据模型解耦。如果视图中没有与数据模型相关联的功能,则不需要视图模型。
如果您在数据模型中有一个对象,其属性在创建后不会更改,并且视图不会修改它,并且可以在UI中以无格式或转换方式呈现,则通过直接公开它,您不会将任何功能与视图耦合。 对于这种情况,您不需要视图模型。
在您的示例中,您可能可以轻松地不创建StateViewModel类,因为这样的类实际上不会做任何事情。

从理论上讲,那是正确的,但在实践中,有时事情并不像人们(其中包括开发人员)希望想象的那样恒定不变,例如州列表可能会在将来扩展以包括其他国家等。 - Aviad P.
1
这并不是会对这个决定产生影响的那种更改。将新状态添加到列表中并不意味着需要在 UI 中可编辑其属性。 - Robert Rossney

1

我会直接通过ViewModel将实体绑定到视图,除非我需要添加特定的属性,例如IsSelected等用于树形视图。如果我必须添加其他属性,则我会让ViewModel包装每个实体属性。


0

你不能在ViewModel中暴露Entity的原因是你不应该用视图特定的代码如IDataErrorInfo、INotifyPropertyChanged、IEditableObject等来污染Entity

Entity是应用程序核心,应该是POCO,可以在各种类型的应用程序中重复使用。例如,如果您开发了一款可以通过移动设备、Web和桌面访问的应用程序,您不需要为每种类型的应用程序创建一个Entity。

解耦的原因?抱歉,但我不同意,因为我认为将Model和ViewModel解耦并没有任何好处,因为无论ViewModel中是否包含Entity,单元测试都能正常工作。

更新

抱歉,我忘记了你使用的是EF4。EF4实体默认支持INotifyPropertyChanged,因此在ViewModel中公开实体是可以接受的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接