利刃 MVVMLight 9:Messenger

来源:http://www.cnblogs.com/wzh2010/archive/2017/05/10/6679025.html
-Advertisement-
Play Games

MVVM的目標之一就是為瞭解耦View和ViewModel。View負責視圖展示,ViewModel負責業務邏輯處理,儘量保證 View.xaml.cs中的簡潔,不包含複雜的業務邏輯代碼。 但是在實際情況中是View和ViewModel之間的交互方式還是比較複雜的,View和ViewModel的分離 ...


      MVVM的目標之一就是為瞭解耦View和ViewModel。View負責視圖展示,ViewModel負責業務邏輯處理,儘量保證 View.xaml.cs中的簡潔,不包含複雜的業務邏輯代碼。

但是在實際情況中是View和ViewModel之間的交互方式還是比較複雜的,View和ViewModel的分離並不是界定的那麼清晰。

比如以下兩種場景:

      1、如果需要某張視圖頁面彈出對話框、彈出子窗體、處理界面元素,播放動畫等。如果這些操作都放在ViewModel中,就會導致ViewModel還是要去處理View級別的元素,造成View和ViewModel的依賴。

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

      2、ViewModel和ViewModel之間也需要通過消息傳遞來完成一些交互。 

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

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

在這種情況下信息只能被傳遞如果接受者類型和目標參數類型匹配,message可以是任何簡單或者複雜的對象,你可以用特定的消息類型或者創建你自己的類型繼承自他們。

Messager類的主要交互模式就是信息接受和發送(可以理解為“發佈消息服務”和“訂閱消息服務”),是不是想到觀察者模式了,哈哈哈。

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

如圖: 

 

 

1、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     }

  結果:

 

2、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     }

 

 結果如下:

 

下載示例代碼

轉載請註明出處,謝謝

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果對象可以改變其狀態,就很難在多個同時運行的任務中使用。這些集合必須同步。如果對象不能改變器狀態,就很容易在多個線程中使用。 Microsoft提供了一個新的集合庫:Microsoft Immutable Collection。顧名思義,它包含不變的集合類————創建後不能改變的集合類。該類在Sy ...
  • 0. 寫在前面 1. 建立運行環境 2. 添加實體和映射資料庫 1. 準備工作 2. Data Annotations 3. Fluent Api 3. 包含和排除實體類型 1. Data Annotations [NotMapped] 排除實體和屬性 2. Fluent API [Ignore] ...
  • 如果需要集合中的元素何時刪除或添加的信息,可以使用ObservableCollection<T>類。這個類是為WPF定義的,這樣UI就可以得知集合的變化。這個類在程式集WindowsBase中定義,需要引用這個程式集。 ObservableCollection<T>類派生自Collection<T> ...
  • 包含不重覆元素的集合稱為“集(set)”。.NET Framework包含兩個集HashSet<T>和SortedSet<T>,它們都實現ISet<T>介面。HashSet<T>集包含不重覆元素的無序列表,SortedSet<T>集包含不重覆元素的有序列表。 ISet<T>介面提供的方法可以創建合集 ...
  • ListView是個較為複雜的控制項 ListView是個較為複雜的控制項 ListView是個較為複雜的控制項 1.定義 把它拽進來,系統會自動在Designer.cs里添加一個 this.listView1 = new System.Windows.Forms.ListView(); 2.初始化,確定 ...
  • 字典表示一種複雜的數據結構,這種數據結構允許按照某個鍵來訪問元素。字典也稱為映射或散列表。 字典的主要特性是能根據鍵快速查找值。也可以自由添加和刪除元素,這有點像List<T>(http://www.cnblogs.com/afei-24/p/6824791.html),但沒有在記憶體中移動後續元素的 ...
  • 1 /// 2 /// 短鏈生成 3 /// 4 public class ShortUrlBuilder 5 { 6 private static readonly string[] Chars = 7 { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h"... ...
  • 一、確定多線程的結束時間,thread的IsAlive屬性 在多個線程運行的背景下,瞭解線程什麼時候結束,什麼時候停止是很有必要的。 案例:老和尚念經計時,2本經書,2個和尚念,一人一本,不能撕破,最短時間念完,問老和尚們念完經書最短需要多長時間。 分析:首先在開始念經的時候給計時,記為A,最後在記 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...