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 代码如下:

   public partial class NessagerForView : Window
{
public NessagerForView()
{
InitializeComponent(); //消息标志token:ViewAlert,用于标识只阅读某个或者某些Sender发送的消息,并执行相应的处理,所以Sender那边的token要保持一致
//执行方法Action:ShowReceiveInfo,用来执行接收到消息后的后续工作,注意这边是支持泛型能力的,所以传递参数很方便。
Messenger.Default.Register<String>(this, "ViewAlert", ShowReceiveInfo);
this.DataContext = new MessengerRegisterForVViewModel();
//卸载当前(this)对象注册的所有MVVMLight消息
this.Unloaded += (sender, e) => Messenger.Default.Unregister(this);
} /// <summary>
/// 接收到消息后的后续工作:根据返回来的信息弹出消息框
/// </summary>
/// <param name="msg"></param>
private void ShowReceiveInfo(String msg)
{
MessageBox.Show(msg);
}
}

ViewModel代码:

  public class MessengerRegisterForVViewModel:ViewModelBase
{ public MessengerRegisterForVViewModel()
{ } #region 命令 private RelayCommand sendCommand;
/// <summary>
/// 发送命令
/// </summary>
public RelayCommand SendCommand
{
get
{
if (sendCommand == null)
sendCommand = new RelayCommand(() => ExcuteSendCommand());
return sendCommand; }
set { sendCommand = value; }
} private void ExcuteSendCommand()
{
Messenger.Default.Send<String>("ViewModel通知View弹出消息框", "ViewAlert"); //注意:token参数一致
} #endregion
}

结果:

2、ViewModel和ViewModel之间的消息交互,ViewModel和ViewModel在很多种场景下也需要通过消息传递来完成一些交互。

比如我打开了两个视图,一个视图是用户信息列表,一个视图是用户信息添加页面,如果想要达到添加信息之后,用户信息列表视图实时刷新,用消息通知无疑是一个很棒的体验。

我们来模拟一下:

MessengerRegisterViewModel代码:

   public class MessengerRegisterViewModel:ViewModelBase
{
public MessengerRegisterViewModel()
{
///Messenger:信使
///Recipient:收件人
Messenger.Default.Register<String>(this,"Message",ShowReceiveInfo);
} #region 属性 private String receiveInfo;
/// <summary>
/// 接收到信使传递过来的值
/// </summary>
public String ReceiveInfo
{
get { return receiveInfo; }
set { receiveInfo = value; RaisePropertyChanged(()=>ReceiveInfo); }
} #endregion #region 启动新窗口 private RelayCommand showSenderWindow; public RelayCommand ShowSenderWindow
{
get {
if (showSenderWindow == null)
showSenderWindow = new RelayCommand(()=>ExcuteShowSenderWindow());
return showSenderWindow; }
set { showSenderWindow = value; }
} private void ExcuteShowSenderWindow()
{
MessengerSenderView sender = new MessengerSenderView();
sender.Show();
} #endregion #region 辅助函数
/// <summary>
/// 显示收件的信息
/// </summary>
/// <param name="msg"></param>
private void ShowReceiveInfo(String msg)
{
ReceiveInfo += msg+"\n";
}
#endregion
}

MessengerSenderViewModel代码:

  public class MessengerSenderViewModel:ViewModelBase
{
public MessengerSenderViewModel()
{ } #region 属性
private String sendInfo;
/// <summary>
/// 发送消息
/// </summary>
public String SendInfo
{
get { return sendInfo; }
set { sendInfo = value; RaisePropertyChanged(()=>SendInfo); }
} #endregion #region 命令 private RelayCommand sendCommand;
/// <summary>
/// 发送命令
/// </summary>
public RelayCommand SendCommand
{
get
{
if (sendCommand == null)
sendCommand = new RelayCommand(() => ExcuteSendCommand());
return sendCommand; }
set { sendCommand = value; }
} private void ExcuteSendCommand()
{
Messenger.Default.Send<String>(SendInfo, "Message");
} #endregion
}

结果如下:

下载示例代码

转载请注明出处,谢谢

利刃 MVVMLight 9:Messenger的更多相关文章

  1. 利刃 MVVMLight 10:Messenger 深入

    1.Messager交互结构和消息类型 衔接上篇,Messeger是信使的意思,顾名思义,他的目是用于View和ViewModel 以及 ViewModel和ViewModel 之间的消息通知和接收. ...

  2. 利刃 MVVMLight

    已经很久没有写系列文章了,上一次是2012年写的HTLM5系列,想想我们应该是较早一批使用HTML5做项目的人. 相比我当时动不动100+的粉丝增长和两天3000+的阅读量,MVVM Light只能算 ...

  3. 利刃 MVVMLight 1:MVVMLight介绍以及在项目中的使用

    一.MVVM 和 MVVMLight介绍 MVVM是Model-View-ViewModel的简写.类似于目前比较流行的MVC.MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的 ...

  4. 利刃 MVVMLight 2:Model、View、ViewModel结构以及全局视图模型注入器的说明

         上一篇我们已经介绍了如何使用NuGet把MVVMLight应用到我们的WPF项目中.这篇我们来了解下一个基本的MVVMLight框架所必须的结构和运行模式. MVVMLight安装之后,我们 ...

  5. 利刃 MVVMLight 3:双向数据绑定

          上篇我们已经了解了MVVM的框架结构和运行原理.这里我们来看一下伟大的双向数据绑定. 说到双向绑定,大家比较熟悉的应该就是AngularJS了,几乎所有的AngularJS 系列教程的开篇 ...

  6. 利刃 MVVMLight 5:绑定在表单验证上的应用

    表单验证是MVVM体系中的重要一块.而绑定除了推动 Model-View-ViewModel (MVVM) 模式松散耦合 逻辑.数据 和 UI定义 的关系之外,还为业务数据验证方案提供强大而灵活的支持 ...

  7. 利刃 MVVMLight 6:命令基础

    在MVVM Light框架中,事件是WPF应用程序中UI与后台代码进行交互的最主要方式,与传统方式不同,mvvm中主要通过绑定到命令来进行事件的处理, 因此要了解mvvm中处理事件的方式,就必须先熟悉 ...

  8. 利刃 MVVMLight 7:命令深入

    上面一篇我们大致了解了命令的基本使用方法和基础原理,但是实际在运用命令的时候会复杂的多,并且有各种各样的情况. 一.命令带参数的情况: 如果视图控件所绑定的命令想要传输参数,需要配置 CommandP ...

  9. 利刃 MVVMLight 4:绑定和绑定的各种使用场景

    一.绑定: 主要包含元素绑定和非元素绑定两种. 1.元素绑定,是绑定的最简单形式,源对象是WPF的元素,并且源对象的属性是依赖项属性. 根据我们之前的知识 ,依赖项属性具有内置的更改通知支持.所以当我 ...

随机推荐

  1. 微信JS分享功能--微信JS系列文章(二)

    概述 在上一篇文章微信JS初始化-- 微信JS系列文章(一)中已经介绍了微信JS初始化的相关工作,接下来本文继续就微信JS的分享功能进行描述,供大家参考. 代码 $(document).ready(f ...

  2. ICC_lab总结——ICC_lab6:版图完成

    ICC_workshop的最后一个实验了.在这次的实验中,由于我使用ICC的版本与workshop的lab不是同一个版本,因此在后面的实验过程不是很顺利,主要是在LVS的过程中,最后的LVS没有通过. ...

  3. 在Windows的DOS中运行java编程中的问题

    1.苦恼着我的就是找不到或无法加载主类!

  4. 一行命令创建 http-server

    一行命令启动http-server总结:1. python2.xpython2 -m SimpleHTTPServer 8000 2. python3.xpython -m http.server 8 ...

  5. instance 怎么获得自己的 Metadata - 每天5分钟玩转 OpenStack(169)

    要想从 nova-api-metadata 获得 metadata,需要指定 instance 的 id.但 instance 刚启动时无法知道自己的 id,所以 http 请求中不会有 instan ...

  6. VC++中经常出现的内存泄露和指针问题

    要养成良好的编程习惯,每次用new开辟的新空间马上先写好释放语句delete.指针在程序中往往有很多细节问题,比如1.指针作为返回值,某个分支中进行赋值返回,另一个分支却没有值.2.指针作为函数参数传 ...

  7. 腾讯云数据库团队:PostgreSQL TOAST技术理解

    作者介绍:胡彬 腾讯云高级工程师 TOAST是"The Oversized-Attribute Storage Technique"的缩写,主要用于存储一个大字段的值.要理解TOA ...

  8. Intellj IDEA 简易教程

    Intellj IDEA 简易教程 目录 JDK 安装测试 IDEA 安装测试 调试 单元测试 重构 Git Android 其他 参考资料 Java开发IDE(Integrated Developm ...

  9. 在hive中直接对timestamp类型取max报错

    之前直接对timestamp类型做max操作, select id,max(updatetime) updatetime from his.tag group by id; 结果查询的结果有的显示为1 ...

  10. word-wrap: break-word;与word-break: break-all;文本自动换行

    word-break:break-all和word-wrap:break-word都是能使其容器如DIV的内容自动换行它们的区别就在于:1,word-break:break-all 例如div宽200 ...