视图模型的MVVMinheritance

我想知道如何在MVVM模式中使用View Models进行inheritance。 在我的应用程序中,我有一个类似于以下内容的数据模型:

class CustomObject { public string Title { get; set; } } class CustomItem : CustomObject { public string Description { get; set; } } class CustomProduct : CustomItem { public double Price { get; set; } } 

在我的应用程序中,我有一个ViewModelBase类,然后将有以下View Models:

  • CustomObjectViewModel
  • CustomItemViewModel
  • CustomProductViewModel

CustomObjectViewModel的粗略实现类似于以下内容:

 class CustomObjectViewModel : ViewModelBase { private readonly CustomObject _customObject; public CustomObjectViewModel( CustomObject customObject ) { _customObject = customObject; } public string Title { // implementation excluded for brevity } } 

对我来说,我的视图模型将以与模型相同的方式扩展自己(CustomItemViewModel扩展CustomObjectViewModel等),这似乎是合乎逻辑的。 但是,我注意到,当我inheritanceinheritance树时,我将添加对同一对象的其他引用。 这对我来说似乎相当过分,并且想知道如何处理这个问题以及是否有可能使它更清洁。

通常,我建议您不要在不同的ViewModel类之间inheritance ,而是让它们直接从公共抽象基类inheritance。
这是为了避免通过使用来自层次结构中较高层的成员污染ViewModel类的接口来避免引入不必要的复杂性,但这些成员与该类的主要目的并不完全一致
inheritance附带的耦合也可能使得在不影响任何派生类的情况下更改ViewModel类很困难。

如果ViewModel类始终引用单个Model对象,则可以使用generics将此规则封装到基类中:

 public abstract class ViewModelBase { private readonly TModel _dataObject; public CustomObjectViewModel(TModel dataObject) { _dataObject = dataObject; } protected TModel DataObject { get; } } public class CustomObjectViewModel : ViewModelBase { public string Title { // implementation excluded for brevity } } public class CustomItemViewModel : ViewModelBase { public string Title { // implementation excluded for brevity } public string Description { // implementation excluded for brevity } } 

与Enrico上述评论相关。 ViewModels不应该与视图紧密耦合,它应该是相反的方式。 视图应与ViewModels松散耦合。 ViewModel不应该知道视图,这允许您轻松地对ViewModel进行unit testing.View与ViewModel之间的所有交互都应该通过ViewModel中的属性实现(动作的ICommand属性和数据绑定的其他属性)。

有一点是真实的,即ViewModel与模型紧密耦合,因此上面使用generics可以实现很多可扩展性。 这是我推荐的模式。

通过提供基本上只暴露属性的ViewModel类,它应该允许您将其扩展到任何类型的表示框架中并利用您之前使用的所有代码。 换句话说,如果正确实现,您可以将ViewModel程序集放入ASP.NET MVC应用程序中,并将视图绑定到属性,并且不会更改代码。

关于MVVM基础知识的一篇好文章是: 这一篇。 我真的认为MVVM是UI开发的最佳选择。 显然,我们不能全部使用它,因为它需要使用MVVM方法从头开始构建应用程序,但是当您构建一个不是问题的新应用程序时。

我与ICommand的一个抱怨是它在PresentationCore Assembly中基本上用于WPF。 如果微软想要松散耦合,它应该完全在另一个程序集中。

我认为这里的问题是每个View应该有一个ViewModel,而不是每个模型都有一个ViewModel。

原因很明显,因为您只能将一个对象设置为DataContext,该对象应该是该View的ViewModel。

我有兴趣看看是否有更好的答案,但是当我遇到同样的问题时,我总是将对象的显式强制转换为私有属性,如下所示:

 class CustomObjectViewModel : ViewModelBase { protected readonly CustomObject CustomObject; public CustomObjectViewModel( CustomObject customObject ) { CustomObject = customObject; } public string Title { // implementation excluded for brevity } } class CustomItemViewModel : CustomObjectViewModel { protected CustomItem CustomItem { get { return (CustomItem)CustomObject; } } public CustomItemViewModel( CustomItem customItem ) :base(customItem) { } } 

它有效,这是我提出的最好的,但对我来说从来没有感觉很干净。