2013-02-08 42 views
10

我在我們的WPF應用程序中使用MVVM模式以允許進行全面的單元測試。 MVVM模式本身工作得很好,但是我正在努力調整模式,這意味着我可以使用WPF的設計時數據支持。在MVVM模式中使用WPF設計數據

正如我使用棱鏡的視圖模型實例通常注入到視圖的構造,像這樣

public MyView(MyViewModel viewModel) 
{ 
    DataContext = viewModel; 
} 

依存關係的視圖模型然後被注入到構造,像這樣

public class MyViewModel 
{ 
    public MyViewModel(IFoo foo, IBar bar) 
    { 
     // ... 
    } 

    // Gets and sets the model represented in the view 
    public MyModel { get; set; } 

    // Read-only properties that the view data binds to 
    public ICollectionView Rows { get; } 
    public string Title { get; } 

    // Read-write properties are databound to the UI and are used to control logic 
    public string Filter { get; set; } 
} 

除了涉及設計數據時,這一般工作得很好 - 我想避免將設計數據特定的類編譯到我發佈的程序集中,因此我選擇使用{d:DesignData}方法而不是{d:DesignInstance}的方法,但是爲了這個工作正常我的ViewModel現在需要有一個無參數的構造函數。另外,爲了能夠在XAML中設置這些屬性,我還經常需要更改其他屬性,以使其具有setter或可修改的集合。

public class MyViewModel 
{ 
    public MyViewModel() 
    { 
    } 

    public MyViewModel(IFoo foo, IBar bar) 
    { 
     // ... 
    } 

    // Gets and sets the model represented in the view 
    public MyModel { get; set; } 

    // My read-only properties are no longer read-only 
    public ObservableCollection<Something> Rows { get; } 
    public string Title { get; set; } 

    public string Filter { get; set; } 
} 

這是令人擔憂的我:

  • 我有一個從未想過會叫,不進行單元測試
  • 有房產setter方法參數的構造函數,只有視圖模型本身應該被稱爲
  • 我的ViewModel現在是一個混亂的屬性,應該由視圖修改,那些不應該 - 這使得它很難告訴一眼看哪段代碼負責維護任何給定的屬性
  • 在設計時設置某些屬性(例如在Filter文本中看到樣式)實際上最終可能會調用ViewModel邏輯! (所以我的視圖模型也需要tollerant否則強制依賴是在設計時失蹤)

有沒有更好的方式來獲得的方式,不影響在WPF MVVM應用程序設計時數據我ViewModel以這種方式?

另外,我應該建立我的ViewModel不同,以便它具有更多的簡單屬性與邏輯分離出其他地方。

回答

-1

我也一直在使用WPF和MVVM實現進行NUnit測試。但是,我的版本與您的版本相反。您首先創建視圖,然後創建模型來控制它。

在我的版本中,我創建了MVVM模型FIRST,並且可以對它進行單元測試,直到母牛回家並且不用擔心任何視覺設計......如果模型被破壞,視覺實現也將如此。在我的MVVM模型中,我有一個方法來「GetTheViewWindow」。所以,當我從我的MVVM基線中派生出來時,每個視圖模型都有其自己的視圖負責。因此,通過虛擬方法,每個實例在應用於生產時都會創建自己的新視圖窗口。

public class MyMVVMBase 
{ 
    private MyViewBaseline currentView; 

    public MyMVVMBase() 
    { // no parameters required } 

    public virtual void GetTheViewWindow() 
    { throw new exception("You need to define the window to get";) } 
} 

public class MyXYZInstanceModel : MyMVVMBase 
{ 
    public override void GetTheViewWindow() 
    { 
     currentView = new YourActualViewWindow(); 
    } 
} 

希望這有助於替代您所遇到的情況。

+2

對我來說有點奇怪,你的虛擬機會依賴於你的視圖。 – 2013-02-09 21:58:06

+0

@GregD,而不是我。我應該能夠擁有這個模型,我可以查詢數據,通過暴露getter/setter設置可能呈現給任何外部「視圖」的標誌。我只是說在這個例子中,它並不需要視圖,但是如果我想啓動一個視圖,每個視圖模型都有自己的目的,比如維護屏幕,事務頭/細節處理等等。如果有相應的視圖,我只需要說鉤子...去調​​用與此mvvm處理程序關聯的視圖。 – DRapp 2013-02-10 01:25:57

+0

那麼設計時數據如何使用這種方法呢? – Justin 2013-02-10 18:55:01

1

首先,我建議您看看this video,其中Brian Lagunas提供了有關MVVM的幾個最佳實踐。 Brian至少參與了Prism的開發,因爲他的名字出現在nuget包信息中。沒有進一步檢查。

在我身邊,我只用棱鏡位,和我的模型和視圖模型總是提供空白構造函數(像什麼布賴恩顯示),數據上下文在視圖中的XAML分配,我設置的屬性值,如:

<MyView.DataContext> 
    <MyViewModel /> 
</MyView.DataContext> 

public void BringSomethingNew() 
{  
    var myView = new View(); 
    (myView.DataContext as ViewModel).Model = myModel; 

    UseMyView(); 
} 

這種方法的另一個好處是,視圖模型在設計創建一次,使用相同的路徑和運行時間,讓你產生更少的對象和保存GC的努力。我覺得這很優雅。

至於到制定者,如果你讓他們私人的設計數據仍然可以工作,如:

public string MyProp { get; private set; } 

好吧,對其進行自定義在您方便的管理NotifyPropertyChange,但你的想法。

現在,我還沒有一個解決方案來管理ObesrvableCollection s(我面臨同樣的問題,雖然在XAML中有多個值有時可以工作......),是的,我同意你必須在未設置屬性時管理案例,例如在構造函數中設置默認值。

我希望這會有所幫助。