MVVM模式解析和在WPF中的實現(五)
View和ViewModel的通訊
系列目錄:
MVVM模式解析和在WPF中的實現(五)View和ViewModel的通訊
MVVM模式解析和在WPF中的實現(六)用依賴注入的方式配置ViewModel並註冊訊息
0x00 還需要些什麼呢
在前面幾篇部落格中我們嘗試去實現了MVVM中的資料繫結、命令繫結和事件繫結。貌似實現的差不多了。我最早嘗試用MVVM去開發的時候也是這麼想的,沒有用第三方框架,甚至只是實現了資料繫結和命令繫結就開搞了,遇到需要訂閱事件的時候就把程式碼寫在後臺。那時候經常自我洗腦:設計模式是死的,人是活的,不能犯教條主義錯誤,後臺寫點程式碼影響不大。我確實很好的貫徹了這個思想,邏輯自然是亂得一塌糊塗。後來認真學習了下,實現了事件繫結,感覺好了很多。但確走向了另一個極端,後臺程式碼多寫一行都會感覺很不爽。還有就是View和ViewModel的依賴,例如當需要在ViewModel中開啟視窗,給視窗傳值,在視窗關閉後獲取返回值時,開啟窗體的動作在ViewModel中進行嗎?這樣ViewModel又產生了對View的依賴了。還有當主窗體按下一個按鈕,然後需要另外一個窗體做出響應的時候,窗體間要如何通訊。當在ViewModel中使用其它執行緒影響到UI時怎麼處理。這篇部落格主要對這些問題簡單說明一下。
0x01 View和ViewModel的通訊
訊息通訊的方式主要受到MVVMLight的啟發,MVVMLight實現了一套略有複雜的訊息通訊,包含了定型別傳送、分組傳送、傳送給包含繼承型別的目標、廣播等。就目前我做的幾個小專案來說,View和ViewModel通訊本身用的就不是那麼頻繁,需求也不算旺盛,所以自己實現了一套比較簡易的訊息通訊。View在例項化的時候註冊訊息,通過一個列表儲存註冊的訊息,訊息在傳送的時候根據條件從列表中找到相應的訊息並執行操作,如下圖所示:
訊息傳送和處理:
比較奇怪的是為什麼要引入一個訊息註冊器,在View的後臺程式碼中直接註冊不就可以了嗎?好吧,其實最初的想法確實比較強迫症,只是單純的不想在後臺中寫入太多的程式碼(我真不是處女座),這樣看上去似乎更高階。不過後來想了下,View對ViewModel(雖然不是介面)和訊息註冊器實際上都算是一種依賴,而且View對ViewModel和訊息註冊器的依賴都是唯一的,也就是說一個View只有一個ViewModel和一個訊息註冊器。這樣可以用控制反轉的方式把對ViewModel和訊息註冊器的依賴一起注入進來,而且在注入過程中可以順便配置ViewModel的Dispatcher以方便跨執行緒修改UI,也可以給ViewModel配置單獨的MessageManager讓View和ViewModel的通訊進入另一個次元,不受其他訊息干擾。這些在討論ViewModel依賴注入的時候將會嘗試。
0x02 關於跨執行緒修改UI
這個順帶提一下,因為實現起來很簡單。在ViewModel中有時會遇到使用其它執行緒修改UI的情況,我之前是通過 App.Current.MainWindow.Dispatcher來獲取UI執行緒的排程器的。當然也可以把UI執行緒的排程器儲存到一個靜態變數中以便隨時訪問。不過我一直沒搞明白MaiWindow的Dispatcher和非MainWindow的Dispatcher有什麼區別,不過還是在ViewModel的基類中加入了Dispatcher這個屬性,這樣在給View注入ViewModel的時候可以把ViewModel的Dispatcher設定為繫結的View的Dispatcher,雖然並不太清楚這有什麼卵用 -_-|||
0x03 示例
這個就沒有示例了:(
實際上之前寫過一個示例,不過那時候的實現還不太成熟,打算把後面一些想法整合一下,程式碼重構後再寫示例。
更多內容歡迎訪問我的部落格:http://www.durow.vip