利刃 MVVMLight 9:Messenger

2017-05-10 11:25:41来源:cnblogs.com作者:翁智华人点击

      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 SendCommand16         {17             get18             {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         #endregion33     }

  结果:

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 ReceiveInfo18         {19             get { return receiveInfo; }20             set { receiveInfo = value; RaisePropertyChanged(()=>ReceiveInfo); }21         }22 23         #endregion24 25 26         #region 启动新窗口27 28         private RelayCommand showSenderWindow;29 30         public RelayCommand ShowSenderWindow31         {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         #endregion60     }

 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 SendInfo14         {15             get { return sendInfo; }16             set { sendInfo = value; RaisePropertyChanged(()=>SendInfo); }17         }18 19         #endregion20         21         #region 命令22 23         private RelayCommand sendCommand;24         /// <summary>25         /// 发送命令26         /// </summary>27         public RelayCommand SendCommand28         {29             get30             {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         #endregion45     }

 结果如下:

下载示例代码

转载请注明出处,谢谢

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台