2011-02-03 113 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知道模型,但不知道視圖,模型知道業務層而不是視圖模型或視圖。

正如您從箭頭(以及其他人提到的)中可以看到的那樣,模型可以通過視圖模型上的單個屬性暴露出來,這意味着該視圖可以通過此模型直接鏈接到模型,或者模型可以在虛擬機上'模型屬性中抽象或重新實現'。