2011-02-03 112 views
1

我目前正在开发一个新的WPF应用程序,并开发了大部分业务逻辑层(即我的模型)。MVVM设计考虑事项

我是关于实现ViewModel类来表示我的应用程序的一个功能。我对Model-View-ViewModel模式相当陌生,我有一个关于在实现我的ViewModel类时最好使用哪种方法的问题。

从网上的例子我一直发现,模型是ViewModel的成员。使用这种方法,ViewModel公开了Model-member的属性,以便它们可以绑定到View中的Model。

例如:

Public Class MyViewModel 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 

    Private _myModel As ModelClass 

    Public Property MyModelPropertyA As Object 
    Get 
     Return _myModel.MyModelPropertyA 
    End Get 
    Set(ByVal value As Object) 
     _myModel.MyModelPropertyA = value 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MyModelPropertyA") 
    End Set 
    Public Property MyModelPropertyB As Object 
    Get 
     Return _myModel.MyModelPropertyB 
    End Get 
    Set(ByVal value As Object) 
     _myModel.MyModelPropertyB = value 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MyModelPropertyB") 
    End Set 
    '.... And so On' 

End Class 

我不喜欢这种做法是事实,有很多的属性,我将重新书写。

所以,我正在考虑在ViewModel中继承模型类而不是使用私有成员的选项。

像这样:

Public Class MyViewModel 
     Inherits MyModel 
     Implements INotifyPropertyChanged 

     Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 

     'Now all of my properties are inherited' 
End Class 

与第二种方法的问题是,我不知道如何将我的模型转换为视图模型的应用程序运行时。

您无法设置viewModelInstance = ModelInstance。

(但你可以设置modelInstance = viewModelInstance)

我在寻找咨询关于如何实现视图模型类的最佳方法。

+0

您对继承的使用很有趣。关于你最后的问题,你需要一个隐藏对象创建的工厂。但是我看到的一个问题是,如果Model对象出现在两个不同的视图中,并且因此具有两个不同的视图模型。如果它已经被实例化为VmA,那么你不能变成VmB。 – HappyNomad 2011-02-03 18:38:19

回答

3

甚至不要考虑从模型继承viewModel - 这将是任何人都不会喜欢的破解。如果你也懒得公开所有的属性(BTW resharper可以自动完成),那么你可以将你的模型包含到viewModel中,并通过一些只读属性提供对它的访问。但是你仍然应该在模型类中实现INotifyPropertyChanged

某些代码(抱歉C#):

class Model : INotifyPropertyChanged 
{ 
    public string Name { get; set; } // this raises PropertyChanged 
} 

class ViewModel 
{ 
    private readonly Model _model; 

    public Model Model { get { return _model; } } 
} 

查看XAML:

<Textbox Text="{Binding Model.Name}" /> 
+0

这不是懒惰的问题。这是一个紧迫的最后期限。如果继承不是最好的方法,并且你认为它是一个“黑客”,那么请解释原因。 – Frinavale 2011-02-03 16:29:20

+1

@Frinavale - 继承可能适用于您的情况,但我会建议将模型添加为属性。我在这种类型的继承中看到了一些缺点:** a)**首先 - 对我来说,M和VM之间的关系是混淆的。就像基本的面向对象的书籍说,狗是从动物继承的,因为狗是一些特定的动物,但没有一个说狗应该从头继承,因为它们都有鼻子,眼睛和耳朵。 ** b)**您的虚拟机接收您的模型具有的功能(不确定您是否有),但想象您在模型中有一些持久性逻辑,是否要保留虚拟机? – Snowbear 2011-02-03 16:43:38

+0

** c)**你将无法(至少没有多重继承)继承你的虚拟机。我的虚拟机通常是从`ViewModelBase`继承而来的,其中一些可能会像`EntityEditorViewModelBase`一样继承自smth。您通过继承Model来限制自己。 ** d)**您将无法使用您的模型在一行(!)代码中对VM进行参数化,相反,您将不得不复制所有属性(希望您不会忘记任何属性?) – Snowbear 2011-02-03 16:46:49

1

视图模型通常包装/封装逻辑关系的视图。使用ViewModel来简单地通过模型数据是不需要的恕我直言。纯粹的方法是定义一个ViewModel并传递这些数据;在某些情况下,这仅仅是不需要的,因为应用程序本质上是简单的。如果应用程序具有任何增长潜力,那么使用ViewModel将是必要的。

如果你有一个Person模型; ViewModel通常可能包含一个属性,该属性公开名为PeopleObservableCollection<Person>。 ViewModel是View的编排器;不是模型的传递。

由于上述原因,您不应将模型与ViewModel绑定,因为它们在理论和实践中应该彼此分离。

1

查看此图取自here

enter image description here

这是指为了确保正确以下的图案优异的图。正如你所看到的,层之间有各种不同的交互方式,但主要是分离。总是要确保每个图层只知道它的父层,而不是子级,即VM知道模型,但不知道视图,模型知道业务层而不是视图模型或视图。

正如您从箭头(以及其他人提到的)中可以看到的那样,模型可以通过视图模型上的单个属性暴露出来,这意味着该视图可以通过此模型直接链接到模型,或者模型可以在虚拟机上'模型属性中抽象或重新实现'。