• 利刃 MVVMLight 9:Messenger


          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+"
    ";
    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     }

     结果如下:

    下载示例代码

    转载请注明出处,谢谢

  • 相关阅读:
    《时间的朋友》2017跨年演讲:观后感
    如何实现目标?
    不患贫而患不均
    科学地定目标(附我的目标)
    书单:我的“基本书”
    你只有非常努力,才能看起来毫不费力
    买书?买知识?
    论知识与技能
    【读书笔记】《代码不朽》
    【工作实践】如何创新?
  • 原文地址:https://www.cnblogs.com/wzh2010/p/6679025.html
Copyright © 2020-2023  润新知