2012-01-05 107 views
4

我的模型由單個主對象組成,用戶也可以添加其他各種對象。添加的對象存儲在主對象中包含的List<object>中,並且它是關聯的子對象。將數據傳遞到數據層

所以如果該項目是一個房子。用戶可以將一些Room對象添加到存儲在List<Room> RoomList中的房屋中。然後每個Room可以有多個Furnishings再次添加存儲在每個房間List<Furnishing> FurnishingsList

問題是如何在MVVM方法中實現這個?當用戶添加一個新對象時,我是否將它添加到ViewModel中的ObservableCollection,以便更新視圖並同時將其添加到掛鉤到VM中的模型中?或者我將它存儲在虛擬機中,直到保存或提交命令,然後將它傳遞給模型?

在我的例子中,我有各種編輯器(每個都是用戶控件)。因此,用戶可以使用一個編輯器在高層編輯房屋,從房屋中添加,編輯和移除房間。而在較低的層面上,使用不同的編輯器編輯每個房間,添加和刪除Furnishings

所以當用戶'編輯'一個房間說。我生產的EditRoomModelView包含說Room。用戶添加,編輯和以其他方式操縱該房間中的傢俱。

在每個命令中最好是同步模型中的數據和ModelViee中的數據。或者,我會將這些更改直接推入模型中,並使ViewModel僅在注入的模型屬性中提供獲取者。但是,這種方式將對象添加到模型列表不會更新視圖。我真的不得不同時將數據添加到ModelView和Model中,因此所有內容都處於相同狀態。

漫不經心,努力尋找一個很好的方法,任何人都明白我在做什麼?

回答

3

的明確調用我不知道有一個單一的,很好的答案觸發。聽起來好像你在辯論如何保持一致性 - 你是否在表示層有一個簡單的傳遞方案,或者你是否在用戶請求中插入並且有邏輯。

如果這就是事實上,這個問題,有各種各樣的因素在起作用。你喜歡在表示層做驗證嗎?應用程序有多複雜,它需要如何擴展?您的視圖模型是否需要在多個地方訪問?

因此,所有考慮到這一點,我可以告訴你如何我個人比較喜歡處理這個問題(特別補充說,你提的問題)。我通常喜歡創建視圖模型來描述用戶對泛型的關注,如EditItemViewModel<T>ListViewModel<T>。所以,在GUI中,會有某種綁定到ListViewModel<Room>的房間列表框。這個虛擬機顯然會暴露一個可觀察的集合,但也可以添加,刪除,編輯命令。

所以,從我的角度來看,表示層,視圖modelly的東西,這個虛擬機要做的是爲其他GUI擔憂路由請求。如果您單擊「添加」來添加房間,則該VM負責通過命令啓動請求,以獲取任何屏幕/窗口/添加房間所需的任何內容,該房間將具有自己的VM。該虛擬機在收到添加請求後,會將生成的數據傳輸對象下傳到驗證發生的域以及任何域操作是必需的。我通常通過服務層處理這個問題。現在,如果域操作成功,服務層將提高某種偶數或回調,讓列表虛擬機知道有變化。當發生這種情況時,列表VM將重新查詢其服務並相應地更新其可觀察集合。現在,您的GUI與全線域一致。

我喜歡這種類型的分層方法的原因是,所有的業務邏輯發生在「下面」的GUI的地方,而GUI不必與本次事件關注自身。從概念上講,GUI只是說「在這裏,域層,用戶想要添加這個 - 做所有這些,並讓任何感興趣的GUI組件知道你什麼時候完成以便它們可以刷新自己」。

我描述這裏自然會招致一些開銷比較簡單的,直通方案或在虛擬機只是一些模型對象重新暴露性質的方案作爲什麼。但是,我個人認爲,從脫鉤角度來看,這種優勢是值得的,尤其是在您擴大應用程序的情況下。它使您能夠從根本上改變域模型的內部交互,而無需改變表示層代碼。

+0

謝謝Erik,當我將新對象成功傳遞到域圖層並將其存儲在'List '中時,如何刷新代表'List '的VM的ObservableCollection?服務層是否重新實例化ObservableCollection以反映更改? – 2012-01-06 18:21:30

+0

即使知道ObservableCollection是什麼(即沒有引用包含它的WPF程序集),我在表示層下面也沒有任何東西。我通常會通知GUI組件的方式是使用事件或回調。舉一個簡單的例子,考慮兩個引用相同服務實例的虛擬機。虛擬機A告訴服務添加一個房間,並且該服務完成添加房間所需的任何魔法。當它完成併成功時,會引發VM B偵聽的事件。當事件發生時,VM B重新查詢所有房間的服務...... – 2012-01-06 18:31:00

+0

在實際實施中,域本身將處理添加,然後引發一個事件,服務將消耗並轉發給VM。但是這裏的想法是這樣的 - 虛擬機只知道如何向服務請求對象(PO​​CO/DTO)以及如何將它們傳遞給更新等操作。所以,服務和虛擬機之間的關係是虛擬機會請求對象(Get/GetAll)和請求操作(Add,Edit等)。虛擬機還會監聽服務事件,稱之爲「OnDirty」,告訴虛擬機何時可能與域不同步。虛擬機然後有重新查詢的負擔。 – 2012-01-06 18:33:53

2

第一:View是你DataModel的一面鏡子,所以總是添加第一Model,只覺得以後如果它推動VmView

二:ViewModel是連接您的ModelView的橋樑,但並不意味着它在同一方式Model是爲了構成。如果您想要向用戶展示所有兒童收藏品,則必須將它們暴露爲屬性,並在​​或​​內部構建其內部關係​​僅具有「原始」收藏品,並且在DataModel之間具有它們之間的有效關係。

+0

我的這一說法「總是先添加到模型中,並認爲只有在如果它推動VM或視圖」,有什麼不對的視圖模型創建其他視圖模型實例,e.g的OrderViewModel創建新OrderLineViewModel實例。 – ColinE 2012-01-05 21:44:21

+0

@ColinE:如果使用增加了一個新的對象,imo,它在'UI'級完成是不可接受的。等什麼?這不是「網絡開發」,我們有時候會維護'用戶層面'上的數據來進行驗證,聚合......因爲數據傳輸費用昂貴,但是在'桌面世界'中,在任何時刻都看不到任何理由我的應用程序生命週期我不能問一個關於當前狀態的'model',並且沒有有效的響應。 – Tigran 2012-01-05 21:52:57

2

從您描述的應用程序聽起來,您的視圖模型層不會顯着修改或塑造您的模型。所以,我會在包裝的模型對象上創建各種視圖模型屬性設置器/獲取器簡單的適配器。這樣,您的模型將在視圖模型更改時立即更新。

但是...如果您需要提供'取消'功能,即用戶打開一個模式窗體來編輯某些視圖模型,但是取消而不是確定的編輯,這種簡單的方法將不起作用。

您提交到模型圖層的時機很少有很大差異,因爲這通常不是一個耗時的過程。更重要的是當模型狀態持續時。這通常是通過保存命令該模型發送到持久性服務(文件/雲等)