MVVM模式解析和在WPF中的實現(六) 用依賴注入的方式配置ViewModel並註冊訊息

durow發表於2015-10-11

MVVM模式解析和在WPF中的實現(六)

用依賴注入的方式配置ViewModel並註冊訊息

系列目錄:

MVVM模式解析和在WPF中的實現(一)MVVM模式簡介

MVVM模式解析和在WPF中的實現(二)資料繫結

MVVM模式解析和在WPF中的實現(三)命令繫結

MVVM模式解析和在WPF中的實現(四)事件繫結

MVVM模式解析和在WPF中的實現(五)View和ViewModel的通訊 

MVVM模式解析和在WPF中的實現(六)用依賴注入的方式配置ViewModel並註冊訊息

0x00 最初的想法

這次主要討論下給View指定ViewModel的事情。一般來說給View指定ViewModel常用的方式有兩種,一種是在View的後臺程式碼中寫DataContext = new ViewModel(),還有一種是在XAML中指定View的DataContext。這兩種方式都使得View對ViewModel產生了依賴,這種情況下可以考慮用依賴注入的方式使取消View對ViewModel的直接依賴。依賴注入一般來說可以通過建構函式注入、通過設定屬性注入,這兩種方法對於View來說都不合適。因此可以使用IoC Container,讓View主動去獲取對應的ViewModel。

其實給View指定一個ViewModel並不屬於頻繁的操作,而且改起來也很容易,費半天勁搞個依賴注入確實不太至於。就像上篇文章中廢了半天勁搞了個View和ViewModel的通訊一樣,用到的概率比較小,而且也有別的方式解決,雖然那種方式並不符合MVVM模式。不過View除了依賴ViewModel之外對訊息註冊器也是會產生依賴的,而且某種型別的View一般來說都依賴固定型別的ViewModel和訊息註冊器,因此可以一次注入兩個依賴,這樣貌似就值了,至少我認為是值了,所以有了ViewModelManager這個類。

0x01 ViewModel和MessageManager的依賴注入

使用靜態類ViewModelManager來當作IoC Container。往IoC Container裡註冊依賴關係一般有兩種方式,一種是將依賴關係以某種形式(例如xml)儲存在外部,一種是在程式中註冊到一個列表裡。我採取第二種做法,因為比較容易:)

程式在啟動時使用ViewModelManager.Register將依賴關係註冊到ViewModelManager中,View在建構函式中呼叫ViewModelManager.SetViewModel(this);來設定View的DataContext並通過依賴的訊息註冊器註冊訊息,訊息註冊器可以為空,代表View不接收訊息。它們的關係如圖所示:

 

需要說明的有兩個地方:

一個是View和ViewModel的對應關係。一般來說一個View對應著一種ViewModel,這樣註冊起來是沒問題的。但這個並不絕對,理論上來說一個View可以將DataContext設定為任意ViewModel,如果一個View可以設定多種ViewModel該如何處理呢,這時候可以在ViewModelManager註冊時新增Token屬性,然後用SetViewModel(this,token)的方式指定特定的ViewModel為DataContext。

另一個是訊息註冊的範圍。因為一般來說ViewModel都是和繫結的View通訊。所以預設情況下,訊息註冊到單獨一個MessageManager中,這個MessageManager儲存ViewModel中,ViewModel使用這個MessageManager傳送訊息,傳送的訊息由View接收。但如果需要和其他View通訊,需要把訊息註冊到MessageManager.Default中,這個物件是static的,要達到這個目的只要在View設定ViewMode時這樣來SetViewModel(this,isGlobalMsg:true)即可。如果ViewModel又想和繫結的View單獨通訊,有時候還需要和別的View通訊,可以在訊息註冊器中註冊時將需要單獨通訊的訊息設定一個Group,ViewModel在傳送訊息時加一個Group過濾一下即可。一個Group可以理解為訊息的單獨一個通道。

順帶一提,好吧只是順帶一提的是,在給View注入ViewModel時,順便把ViewModel的UIDispatcher屬性設定為了View的Dispatcher,雖然我不知道這有什麼用。但這樣在ViewModel中使用UIDispatcher時即為相關的View的Dispatcher。如果要使用MainWindow的Dispatcher可以通過DispatcherHelper.Dispatcher或者App.Current.MainWindow.Dispatcher獲得。

0x02 寫在最後

到此為止我能想到的MVVM框架的功能算是基本實現了,遇到的需求十分有限,才能也十分有限,能想到的就這幾個了,歡迎回復討論,也歡迎加我QQ16141860交流。之前一直是在TestArea這個倉庫裡進行測試,現在這個小框架整理了下,放到AyxMVVM倉庫裡了。現在有些想法還不太成熟,使用過程中遇到問題也會隨時修正,以後就都修改到AyxMVVM中了,TestArea中的MyMVVM不再維護了。另外給倉庫起名真是件麻煩事,乾脆統一都用Ayx+XXX的方式,這樣既容易重複的概率又十分小。Ayx是我名字拼音的首字母,想想看以拼音A開頭的姓氏之少就能想到幾乎不會出現重複了。最後,10月6日看了微軟的秋季產品釋出會後信仰充值成功。對UWP十分感興趣,下一步打算學習一下。

0x03 關於AyxMVVM

https://github.com/durow/AyxMVVM

 


更多內容歡迎訪問我的部落格:http://www.durow.vip

相關文章