利刃 MVVMLight 9:Messenger

      MVVM的目標之一就是爲了解耦View和ViewModel。View負責視圖展現,ViewModel負責業務邏輯處理,儘可能保證 View.xaml.cs中的簡潔,不包含複雜的業務邏輯代碼。設計模式

可是在實際狀況中是View和ViewModel之間的交互方式仍是比較複雜的,View和ViewModel的分離並非界定的那麼清晰。函數

好比如下兩種場景:動畫

      一、若是須要某張視圖頁面彈出對話框、彈出子窗體、處理界面元素,播放動畫等。若是這些操做都放在ViewModel中,就會致使ViewModel仍是要去處理View級別的元素,形成View和ViewModel的依賴。this

最好的辦法就是ViewModel通知View應該作什麼,而View監聽接收到命令,並去處理這些界面須要處理的事情。spa

      二、ViewModel和ViewModel之間也須要經過消息傳遞來完成一些交互。 設計

      而MVVM Light  的 Messenger類,提供瞭解決了上述兩個問題的能力:code

Messenger類用於應用程序的通訊,接受者只能接受註冊的消息類型,另外目標類型能夠被指定,用Send<TMessage, TTarget>(TMessage message) 實現,對象

在這種狀況下信息只能被傳遞若是接受者類型和目標參數類型匹配,message能夠是任何簡單或者複雜的對象,你能夠用特定的消息類型或者建立你本身的類型繼承自他們。blog

Messager類的主要交互模式就是信息接受和發送(能夠理解爲「發佈消息服務」和「訂閱消息服務」),是否是想到觀察者模式了,哈哈哈。繼承

MVVM Light Messenger 旨在經過簡單的設計模式來精簡此場景:任何對象均可以是接收端;任何對象均可以是發送端;任何對象均可以是消息。

如圖: 

 

 

 

一、View和ViewModel之間的消息交互

在View和ViewModel中進行消息器註冊,至關於訂閱服務。包含消息標誌、消息參數和消息執行方法。以下:

消息標誌token:ViewAlert,用於標識只閱讀某個或者某些Sender發送的消息,並執行相應的處理,因此Sender那邊的token要保持一致

執行方法Action:ShowReceiveInfo,用來執行接收到消息後的後續工做,注意這邊是支持泛型能力的,因此傳遞參數很方便。

View.xaml.cs 代碼以下:

 1   public partial class NessagerForView : Window
 2     {
 3         public NessagerForView()
 4         {
 5             InitializeComponent();
 6 
 7             //消息標誌token:ViewAlert,用於標識只閱讀某個或者某些Sender發送的消息,並執行相應的處理,因此Sender那邊的token要保持一致
 8             //執行方法Action:ShowReceiveInfo,用來執行接收到消息後的後續工做,注意這邊是支持泛型能力的,因此傳遞參數很方便。
 9             Messenger.Default.Register<String>(this, "ViewAlert", ShowReceiveInfo);
10             this.DataContext = new MessengerRegisterForVViewModel();
11             //卸載當前(this)對象註冊的全部MVVMLight消息
12             this.Unloaded += (sender, e) => Messenger.Default.Unregister(this);
13         }
14 
15         /// <summary>
16         /// 接收到消息後的後續工做:根據返回來的信息彈出消息框
17         /// </summary>
18         /// <param name="msg"></param>
19         private void ShowReceiveInfo(String msg)
20         {
21             MessageBox.Show(msg);
22         }
23     }

 ViewModel代碼:

 1  public class MessengerRegisterForVViewModel:ViewModelBase
 2     {
 3 
 4         public MessengerRegisterForVViewModel()
 5         {
 6           
 7         }
 8 
 9         #region 命令
10 
11         private RelayCommand sendCommand;
12         /// <summary>
13         /// 發送命令
14         /// </summary>
15         public RelayCommand SendCommand
16         {
17             get
18             {
19                 if (sendCommand == null)
20                     sendCommand = new RelayCommand(() => ExcuteSendCommand());
21                 return sendCommand;
22 
23             }
24             set { sendCommand = value; }
25         }
26 
27         private void ExcuteSendCommand()
28         {
29             Messenger.Default.Send<String>("ViewModel通知View彈出消息框", "ViewAlert"); //注意:token參數一致
30         }
31 
32         #endregion
33     }

  結果:

 

二、ViewModel和ViewModel之間的消息交互,ViewModel和ViewModel在不少種場景下也須要經過消息傳遞來完成一些交互。

好比我打開了兩個視圖,一個視圖是用戶信息列表,一個視圖是用戶信息添加頁面,若是想要達到添加信息以後,用戶信息列表視圖實時刷新,用消息通知無疑是一個很棒的體驗。

咱們來模擬一下:

MessengerRegisterViewModel代碼:

 1   public class MessengerRegisterViewModel:ViewModelBase
 2     {
 3         public MessengerRegisterViewModel()
 4         {
 5             ///Messenger:信使
 6             ///Recipient:收件人
 7             Messenger.Default.Register<String>(this,"Message",ShowReceiveInfo);
 8         }
 9 
10 
11         #region 屬性
12 
13         private String receiveInfo;
14         /// <summary>
15         /// 接收到信使傳遞過來的值
16         /// </summary>
17         public String ReceiveInfo
18         {
19             get { return receiveInfo; }
20             set { receiveInfo = value; RaisePropertyChanged(()=>ReceiveInfo); }
21         }
22 
23         #endregion
24 
25 
26         #region 啓動新窗口
27 
28         private RelayCommand showSenderWindow;
29 
30         public RelayCommand ShowSenderWindow
31         {
32             get {
33                 if (showSenderWindow == null)
34                     showSenderWindow = new RelayCommand(()=>ExcuteShowSenderWindow());
35                 return showSenderWindow; 
36             
37             }
38             set { showSenderWindow = value; }
39         }
40 
41         private void ExcuteShowSenderWindow()
42         {
43             MessengerSenderView sender = new MessengerSenderView();
44             sender.Show();
45         }
46 
47         #endregion 
48         
49 
50         #region 輔助函數
51         /// <summary>
52         /// 顯示收件的信息
53         /// </summary>
54         /// <param name="msg"></param>
55         private void ShowReceiveInfo(String msg)
56         {
57             ReceiveInfo += msg+"\n";
58         }
59         #endregion
60     }

 

 MessengerSenderViewModel代碼:

 1  public class MessengerSenderViewModel:ViewModelBase
 2     {
 3         public MessengerSenderViewModel()
 4         {
 5 
 6         }
 7 
 8         #region 屬性
 9         private String sendInfo;
10         /// <summary>
11         /// 發送消息
12         /// </summary>
13         public String SendInfo
14         {
15             get { return sendInfo; }
16             set { sendInfo = value; RaisePropertyChanged(()=>SendInfo); }
17         }
18 
19         #endregion
20         
21         #region 命令
22 
23         private RelayCommand sendCommand;
24         /// <summary>
25         /// 發送命令
26         /// </summary>
27         public RelayCommand SendCommand
28         {
29             get
30             {
31                 if (sendCommand == null)
32                     sendCommand = new RelayCommand(() => ExcuteSendCommand());
33                 return sendCommand;
34 
35             }
36             set { sendCommand = value; }
37         }
38 
39         private void ExcuteSendCommand()
40         {
41             Messenger.Default.Send<String>(SendInfo, "Message");
42         }
43 
44         #endregion
45     }

 

 結果以下:

 

下載示例代碼

轉載請註明出處,謝謝

相關文章
相關標籤/搜索