MVVMLight使用前觀看

我想,現在已經有不少朋友在項目中使用了MVVMLight了吧,如果你正在做WPF,Silverlight,Windows Phone的開發,那麼,你有十分必要的理由瞭解MVVM和MVVMLight。我寫這篇文章的目的,是給大家做一個總結,以便更多的朋友瞭解並掌握MVVM。

 

首先,要說一下MVVM的概念。MVVM嚴格來說,並不是一種框架,而是一個設計的模式吧。與它有關的設計模式還有MVC (現在廣泛用於Web應用中),以及MVP(之前有用過在Windows Forms和WPF中)

 

如果你希望對MVVM有更加感性地認識,我推薦你看下面這篇文章。

 

這篇文章寫得實在太好了,我很欣賞這樣的技術人才,能把一個抽象問題有層次地講清楚。(我強烈建議對MVVM的概念瞭解不深的朋友,認真讀這篇文章,而不要急於用MVVMLight,因爲MVVM是一種模式,而MVVMLight只是其中一種具體的實現)

 

然後,我要說一下MVVMLight吧,剛纔說了,它是一種MVVM的實現。自然它不是唯一的一種實現,但現在大家公認的是,它是比較好的一個實現。就我個人的體會來說,我以前用過微軟提供的Prism中的MVVM特性,但老實說,可能Prism的目標太大了,所以在MVVM這個具體的點上,實在不是那麼好用。

 

值得一說的是,從使用Prism轉換到使用MVVMLight過程相當簡單,如果有類似情況的朋友,不要有什麼顧慮。我這裏不是說Prism不好,它與Mvvmlight嚴格來說,不是一個重量級的產品。MVVMLight專注與MVVM的實現,自然更加靈活

 

接下來,我認爲要學習MVVMLight最好的Quick start,就是作者自己寫的這個網頁

 

通過這個文章,我們可以很清楚地瞭解MVVMLight的設計思路和包含的有關組件,無需太多補充,文章淺顯易懂,確實是我們要學習的一個榜樣

請注意,我這篇文章並非逐一講解MVVMLight的細節功能使用,我主要提一些重點,並且分享一些我的看法和觀點,當然這僅是我一家之言,不見得完全正確。

事實上針對如何使用的方面,已經有不少文章了,大家可以參考

http://zzk.cnblogs.com/s?w=mvvmlight

另外一方面,我覺得大家其實要自己多動手纔會有實際的收穫。MVVMLight使用並不難,在使用中大家可以領會到更多。

 

實際上,我們經常談論MVVMLight的時候,其實談的是MVVMLight Toolkit,它主要是爲了更加方便開發人員使用MVVMLight,它會在本地的GAC(Global Assembly Cache)中分別安裝針對WPF,Silverlight,Windows Phone的Assembly(分別各自有兩個Assembly),並且在Visual Studio中添加相應的項目以及項模板,更加貼心的一點是,它還提供了幾個代碼段。

 

有的朋友可能會問,那麼MVVMLight到底是什麼呢?呃,MVVMLight嘛,就是MVVMLight Toolkit的名稱啦 Be right back,有點繞對吧,放鬆點,不要那麼較真嘛

 

那麼,如果你像我一樣,不安裝MVVMLight Toolkit,如何使用MVVMLight呢?實際上很簡單,我更加習慣於使用nuget package 來獲取最新的MVVMLight的Library,並將它們添加到項目中來。

 

你可以通過這個菜單打開nuget package explorer,如下圖所示,然後,你可以在Online裏面搜索MVVMLight,或者像我這樣在Recent package中直接就可以Install。(nuget package是會被緩存在本地的,所以即便沒有鏈接到網絡,也可以正常使用)

 

既然可以緩存在本地,那麼其實和安裝到GAC是沒有太大區別的,不是嗎?

而且用這種方式還有一個好處,你總是可以得到最新的版本,因爲nuget package是自動有更新提示的。而如果你是用Toolkit的話,則得不到更新的提示。(據可靠消息,MVVMLight將很快有4.0這個版本)

 

很好,你現在已經知道如何將MVVMLight添加到項目中,接下來就是該讓它發揮威力的時候啦。大家一定要理解MVVM的兩個核心目標

1.讓UI界面與邏輯能夠很好地分離又協同工作。

2.讓邏輯代碼更具有可測試性。

 

我們先來說說分離並協同這個目標,在MVVMLight中主要通過什麼實現的呢?它提供了ViewModelBase這個基類,可以讓我們很方便地編寫ViewModel。從下面的截圖可以看出,它提供了很多有用的特性,例如判斷是否在設計狀態(IsInDesignMode),以及觸發屬性更改通知(RaisePropertyChanged),尤其是後者,這可以說是MVVM的根基,爲什麼這麼說呢?UI與邏輯的分離並且協同工作,關鍵就在於WPF和Silverlight有強大的數據綁定機制,而數據綁定機制之所以能夠強大,就是因爲WPF和Silverlight中引入的依賴屬性(Dependency Property)的機制,而依賴屬性,區別於普通屬性的最重要一點就是既可以有單向綁定,也可以有雙向綁定,而且屬性更改之後,可以通知到所有綁定目標上面。

 

除了很好的支持綁定,UI與邏輯分離並協作的另外一個重要機制,就是命令(command)機制。在MVVMLight中,它提供了兩個基本的命令:RelayCommand和RelayCommand<T>

 

這兩個命令其實沒有本質區別,只不過後者是支持泛型的一個參數的,就是可以從命令源接受參數數據。

需要注意的是,這兩個命令只適合綁定在基於按鈕的Click事件上面。例如Button,HyperlinkButton是最常見的。例如下面的例子

 

 

這個綁定的意思,其實就是說,當這個Button被點擊了之後,調用ViewModel中的SaveCommand

如果需要傳遞參數過去呢,就是下面這樣啦。我舉了兩個例子,第一個例子參數是一個常數,而第二個例子參數是一個綁定值,這都是允許的

 

 

但問題是,如果我要綁定其他事件呢?例如MouseMove事件,該怎麼辦呢?在MvvmLight.Extras這個程序集裏面,單獨又給出了一個Command綁定方式,叫EventToCommand,顧名思義,它可以將任何事件綁定到一個命令

 

要使用這個略微麻煩一些,請看下面的例子

 

 

所以,綁定(尤其是雙向綁定)和命令是MVVM的精髓,但實際要認真講起來,MVVMLight這方面實現得其實也沒有什麼特別突出的,其他一些框架也都是這麼做的。以前沒有這些框架之前,我們也是這麼寫的,無非是代碼會多一些而已。

有童鞋可能會說了,屬性綁定我們可以理解,但爲嘛要這麼麻煩去綁定命令呢?直接在xaml.cs裏面寫不就完了嗎?請注意,MVVM的一個目標就是讓xaml.cs代碼中儘量少,極端的情況是沒有任何用戶代碼。這樣才能實現UI與邏輯的分離,所以儘可能地用Command來做。

這裏我也分享我的個人經驗,一定會有的時候,你沒有辦法全部用Command,而不在xaml.cs中寫任何代碼。那個時候,你也大可像我一樣,將代碼寫一些在xaml.cs中也無妨。典型的情況,是希望在視圖裏面接受消息(下面就要講到),並且更新界面的一些效果,例如啓動動畫。這裏面是一個度的把握,並無絕對的好壞。我已經看到有人心領神會地點頭了,所謂隨機應變,大家要有一定的靈活性。

 

不過,Mvvmlight的一個創造性的設計,是它的Message(消息)機制它讓View和ViewModel,以及ViewModel之間通訊變得相當方便,甚至神奇。我相當欣賞這個設計,這是Mvvmlight之所以稱爲Mvvmlight的原因。

具體來說,它提供了一個Messenger類型,可以用來發送和接收消息,它還提供了默認的幾種消息類型。

Messenger class (and diverse message types) to be used to communicate within the application. Recipients only receive the message types that they register for. Additionally, a target type can be specified, in which case the message will only be transmitted if the recipient's type matches the target parameter.
Messages can be anything from simple values to complex objects. You can also use specialized message types, or create your own types deriving from them.
More information about the Messenger class.

  • MessageBase: A simple message class, carrying optional information about the message's sender.
  • GenericMessage<T>: A simple message with a Content property of type T.
  • NotificationMessage: Used to send a notification (as a string) to a recipient. For example, save your notifications as constant in a Notifications class, and then send Notifications.Save to a recipient.
  • NotificationMessage<T>: Same as above, but with a generic Content property. Can be used to pass a parameter to the recipient together with the notification.
  • NotificationMessageAction: Sends a notification to a recipient and allows the recipient to call the sender back.
  • NotificationMessageAction<T>: Sends a notification to a recipient and allows the recipient to call the sender back with a generic parameter.
  • DialogMessage: Used to request that a recipient (typically a View) displays a dialog, and passes the result back to the caller (using a callback). The recipient can choose how to display the dialog, either with a standard MessageBox, with a custom popup, etc…
  • PropertyChangedMessage<T>: Used to broadcast that a property changed in the sender. Fulfills the same purpose than the PropertyChanged event, but in a less tight way.

一個稍微具體一點的例子,請參考

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章