2012-12-12 76 views
7

我在Internet上看到的WPF MVVM應用示例考慮VM與服務層進行交互的層,該服務層使用來自外部庫的「舊」事件,或者與交互網頁使用HTTP或其他。但是如果我自己構建所有的M,V,VM,服務和其他部分呢?如何正確構建服務層和視圖模型層之間的交互?我可以將ObservableCollection<OrderModel>放入服務中,並將其從視圖模型中返回,或者它被認爲是不好的方法,並且有更好的替代方法嗎?WPF MVVM應用服務層中的ObservableCollection

回答

6

你可以做到這一點 - 當然你可以。做這種事情的主要原因是減少多個WPF應用程序的重複。

但是,根據您的服務層/數據層實施情況,您在某些情況下可能遇到的挑戰是長期運行的服務,這些服務反過來使用數據庫連接。 ObservableCollections從服務層自動將應用程序所做的更改同步到數據存儲的角度來看是誘人的;但是,如果要傳達源自數據本身的更改(即響應某些其他創建/修改數據的過程),它會變得複雜。

由於服務層不再是引用的唯一所有者,服務層不能真正替代實例(即在大規模更改的情況下) - 但即使可以,替換實例也會非常多打破UI對集合的綁定。

所以你堅持嘗試保持一個實例是最新的。如果您的服務綁定到數據庫,那麼除非您在服務中對某種形式的長時間運行的監視進程進行編碼,否則保持ObservableCollection在拋出後保持最新狀態的唯一簡單方法是將數據庫連接/上下文(在Linq to Sql或EF的情況下)打開 - 因爲否則相關的對象等將無法檢索(除非您強制所有對象一次讀取 - 這是不可擴展的)。

好的,所以可以編寫某種形式的管理層來管理你的連接 - 除了不可避免的輪詢,或者可能使用的SQL Server通知之外,我相信代碼可能會變得非常複雜。

這就是說,它確實取決於 - 特定的問題是需要注意的問題,但它可能是你有一個架構和環境,其中這些事情根本無關緊要。

我的建議,如果你想嘗試 - 繼續。爲了我?我想過 - 除了將INotifyPropertyChanged添加到某些域模型之外,我堅持認爲應用程序擁有自己的VM。多個應用程序可能共享相同的VM - 但這不會在服務層本身內部。

服務層以典型的一次性方式提供對數據和業務邏輯的訪問。虛擬機模式中的類旨在具有更長的使用壽命 - 並且嘗試編寫長時間運行的服務層是非常難以完成的 - 特別是如果您希望它嘗試並解決所有未來應用程序可能出現的所有問題。不可避免的是,最終只會在服務層中爲單個應用程序提供編碼服務或虛擬機類型 - 在這種情況下,它可能已經進入該應用程序的代碼庫。

0

我不會這麼做,原因很多。他們被記錄在這裏:Common mistakes with an observable collection

作者經歷了人們與他們犯下的幾個錯誤,包括在服務層使用它們。

+0

該文章在「在模型中使用它」一節中指出,在模型中使用OC是不好的,但我看到很多示例,當模型按原樣放入視圖中時,沒有任何轉換。其中一條建議是:「如果模型實現INotifyPropertyChanged,則使用它;否則,將其轉換」。因此,在模型中使用可觀察的集合並不被認爲是每個人都不好的做法......無論如何,問題是:什麼是替代方式,正確的方式? – Athari

+0

我相信另一種方式(正確的方式)是使用IEnumerable。像@PeteH建議的那樣,儘量只使用OC,儘可能在你的ViewModel中使用。然後編寫一個CollectionViewModel類,將ViewModels的ObservableCollection公開爲屬性,並訂閱OnCollectionChanged等。 – Heliac

2

我只能從與「可觀察」方面相關的點使用ObservableCollection,這通常是VM向V暴露某些東西。進一步向下(即M),我會試圖堅持列表和集合等更通用的東西(除非你特別需要其他東西)。在任何情況下,VM都很容易創建基於任何舊IEnumerable的ObservableCollection。

儘管有一個合理的問題,尤其是當ObservableCollection在System.Collections命名空間中的位置似乎表明Microsoft並沒有特別將其視爲專門類(當然不是wpf專用的)。

+0

堅持使用「傳統」列表和枚舉類型的問題是,我仍然需要通過viewmodel更新視圖,添加到列表中;所以viewmodel需要被服務通知一個新的項目。如果我添加事件,它會看起來像一個可觀的集合的不好(可能是越野車)實現... – Athari

+0

@Athari我可以看到你從哪裏來 - 它實際上是沒有意義的,你實現自己的ObservableCollection。再往下看,該服務如何知道事情已經改變? – PeteH

+0

@Athari - 這正是我所做的。當我以編程方式添加一個新項目(即不使用DataGrid新行,但添加一個實體),我有一個OnEntityAdded事件,我從我的存儲庫中的Create方法拋出:** OnEntityAdded(new ModelEntityAddedEventArgs(entity))** 。正如你所看到的,實體被傳遞給事件參數。我的服務層訂閱此事件。 – Heliac