2011-08-24 71 views
17

我無法理解如何在涉及到列表/集合時應用MVVM模式。如何使用集合構造MVVM?

說出MainModel有幾個屬性和方法,以及含有其他DetailModel對象的列表。 DetailModel對象可以添加,刪除或重新排序。

的的MainView會顯示相關的根模式中的一些控制,並可以從列表中填充的列表框。每個項目都將通過DetailModelView UserControl擁有自己的子視圖。

最後,有一個MainViewModel。它具有由MainModel的屬性和方法支持的屬性,綁定到主視圖,更改通知使所有內容保持同步。 (到現在爲止,我很舒服的模式 - 更多的情況下,說明這有我丟失的東西根本...)

當涉及到處理名單,我感到困惑。我遇到了幾個例子,其中MainViewModel只是將DetailModel的列表公開給視圖,而DetailModelViews直接綁定到模型上。這功能,但是有問題。它並不總是遵循該模式(不存在DetailViewModel),並且它促使我在我的詳細模型中包含一些與UI相關的代碼。在我看來,MainViewModel應該公開一個用於UI綁定的DetailViewModel列表,但我堅持如何實現這樣的事情!

應該如何管理兩個列表(DetailModels和DetailViewModels)?我真的很困惑,因爲我最初填充DetailViewModel列表,以及如何處理添加,刪除或更改項目的順序以保持它們的同步!

回答

9

通常Models只不過是數據對象。他們不應該包含任何代碼來執行諸如從列表中添加/刪除項目等操作。這是ViewModel's工作。

在你的情況,我會創建一個MainViewModel具有以下特性:

  • ObservableCollection<DetailViewModel> Details
  • ICommand AddDetailCommand
  • ICommand RemoveDetailCommand

如果您MainModel類是一個數據對象,可以將其公開,也可以是MainViewModel的屬性。公開它的屬性是「MVVM純粹」方法,而公開整個模型有時更實用。您的MainViewModel負責創建初始列表DetailViewModels,並負責添加/刪除這些項目。例如,在PropertyChanged事件爲MainViewModel.MainModel屬性,它可能會重建MainViewModel.Details收集和CollectionChanged事件的MainViewModel.Details屬性將更新MainViewModel.MainModel.Details

+1

這非常簡潔地描述了最終解決方案。我的「MainViewModel」也有命令將列表中的選定項目向上或向下移動... – mbmcavoy

4

你是對有一個單獨的DetailModels列表和DetailViewModels列表。 DetailViewModels列表應該是ObservableCollection<DetailViewModel>類型的屬性。當您設置模型(或在構造的時候,如果你通過模型到您的視圖模型的構造函數)。

private ObservableCollection<DetailViewModel> m_details; 
public IEnumerable<DetailViewModel> Details 
{ 
    get { return m_details; } 
} 

您可以訂閱m_details可以填充可觀察名單。 CollectionChanged。這是您可以處理模型中列表內容重新排序的地方。

我希望這會有所幫助。

2

以我的經驗,唯一一次用暴露模型對象的視圖脫身是如果你正在做簡單的只讀呈現,例如在ComboBox中顯示一個字符串屬性。如果存在任何涉及該對象的實際UI(特別是涉及雙向數據綁定的UI),則需要視圖模型。

通常情況下,主虛擬機的構造看起來像這樣:

public MasterViewModel(MasterModel m) 
{ 
    _Model = m; 
    _Detail = new ObservableCollection<DetailViewModel>(m.Detail); 
} 

其中MasterModel.DetailDetailModel對象的集合,並_Detail是針對使用者容易看到一個Detail屬性支持字段。

至於添加,刪除,重新排序並在該列表中的項目而言,在UI至少這將通過命令行MasterViewModel來完成,它必須既操縱和MasterModel.DetailMasterViewModel.Detail。這有點痛苦,但除非你想在MasterModel.Detail的每次更改後重新填充MasterViewModel.Detail,否則這實在是不可避免的。另一方面,如果您想知道「爲什麼我需要爲視圖模型編寫單元測試?」,現在您知道了。

+0

我還在我的解決辦法,但我想在這裏指出一個很大的幫助:「每次更改後重新填充MasterViewModel.Detail MasterModel.Detail「奇怪的是,這種想法並沒有發生在我身上!我必須在初始化時建立它,所以我可以隨時重建。 – mbmcavoy

+2

我在想'新的ObservableCollection (m.Detail);'會起作用,因爲'm.Detail'的類型與通過ObservableCollection泛型指定爲''的類型不同。我懷疑它會起作用。 –

1

這裏有一個答案,我認爲解決這個問題非常漂亮的使用ObservableViewModelCollection<TViewModel, TModel>

這很好,懶惰。它在ctor中需要一個ObservableCollection和一個ViewModelFactory。我喜歡它,因爲它保持它所屬模型層的狀態。 GUI上的用戶操作可以在VM上通過公共方法調用M上的命令,任何M層產生的更改都將由該鏈接中的類自動處理。

https://stackoverflow.com/q/2177659/456490

注意我的關於SL與WPF評論