Messenger
Messenger
Mvvm提倡View和ViewModel的分离,View只负责数据的显示,业务逻辑都尽可能放到ViewModel中,
保持View.xaml.cs中的简洁(没有任何代码,除了构造函数),但是某些场景下也不必一定要保持
View.xaml.cs中的简洁,例如动画。我们想要让界面酷炫一点,就需要故事版,故事版中必然有与
控件相关的,动画和界面耦合很紧,并且也没有办法分离(或许有呢),我们大可直接将动画的逻辑
就放置到View的后台代码中,动画的触发条件由ViewModel发出,这里我们就要借助Messenger来完成
消息的传递。不仅View和ViewModel可以通过消息传递,ViewModel和ViewModel也需要通过消息传递
来完成一些交互。
Messenger的使用首先要注册消息,消息的标志是什么,消息接受的参数是什么,收到消息后执行什么
操作,然后是发送消息,向哪个消息发送信息,参数是什么。使用上和事件的订阅,事件的触发是一样的。
ViewModel之间通信
这个例子中,我们打开两个窗口(注意是同一个程序中,当初接触的时候不了解其原理,以为是Windows通信
机制中的消息通信,还傻傻的打开两个Application,让他们通信),窗口2向窗口1发送消息,窗口1显示接受到的消息。
我们先来看窗口1是怎么注册消息的
AppView1.xaml
<Window x:Class="MessengerDemo.Views.AppView1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MessengerDemo.Views" DataContext="{Binding Source={StaticResource Locator},Path=View1}"
mc:Ignorable="d"
Title="AppView1" Height="300" Width="300">
<Grid>
<TextBlock Text="{Binding Msg}"></TextBlock>
</Grid>
</Window>
AppView1Model.cs
public class AppView1Model : ViewModelBase
{
private string _msg;
public string Msg
{
get
{
return _msg;
}
set
{
_msg = value;
RaisePropertyChanged(() => Msg);
}
}
public AppView1Model()
{
Messenger.Default.Register<string>(this, MessageToken.SendMessageToken, (msg) =>
{
Msg = msg;
});
}
}
注意:这里使用了一个静态类MessageToken,它的作用是定义消息标志,也是通过它区分不同的消息
MessageToken.cs
public static class MessageToken
{
/// <summary>
/// 动画信息标志
/// </summary>
public static readonly string AnimateMessageToken;
/// <summary>
/// 发送消息标志
/// </summary>
public static readonly string SendMessageToken;
static MessageToken()
{
AnimateMessageToken = nameof(AnimateMessageToken);
SendMessageToken = nameof(SendMessageToken);
}
}
这里定义了2个消息类型,一个用于动画演示,一个用于发送消息。
我们再来看窗口2是怎么发送消息的
AppView2.xaml
<Window x:Class="MessengerDemo.Views.AppView2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MessengerDemo.Views" DataContext="{Binding Source={StaticResource Locator},Path=View2}"
mc:Ignorable="d"
Title="AppView2" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Msg}"></TextBox>
<Button Width="100" Height="30" Grid.Row="1" Content="Send" Command="{Binding SendCommand}"></Button>
</Grid>
</Window>
AppView2Model.cs
public class AppView2Model : ViewModelBase
{
private string _msg;
public string Msg
{
get
{
return _msg;
}
set
{
_msg = value;
RaisePropertyChanged(() => Msg);
}
}
public RelayCommand SendCommand
{
get; set;
}
public AppView2Model()
{
SendCommand = new RelayCommand(() =>
{
Messenger.Default.Send<string>(Msg, MessageToken.SendMessageToken);
});
}
}
这里使用的是同一个MessageToken,这样调试的时候也方便查找。这里我们发送消息时,传递的参数是字符串,
这里可以传递任何类型。
View和ViewModel之间通信
在来看一个动画的,动画的逻辑都写到了View的后台代码中,ViewModel发送触发动画的消息
AppView1.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Msg}"></TextBlock>
<Button Width="100" Height="30" Grid.Row="1" Content="执行动画" x:Name="btn" Command="{Binding AnimateCommand}">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
AppView1.xaml.cs
public partial class AppView1 : Window
{
private Storyboard _storyboard;
public AppView1()
{
InitializeComponent();
_storyboard = new Storyboard();
DoubleAnimation doubleAnimation = new DoubleAnimation(0, 180, new Duration(new TimeSpan(0, 0, 2)));
Storyboard.SetTarget(doubleAnimation, btn);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
_storyboard.Children.Add(doubleAnimation);
Messenger.Default.Register<string>(this, MessageToken.AnimateMessageToken, (msg) =>
{
_storyboard.Begin();
});
}
}
AppView1Model.cs
public class AppView1Model : ViewModelBase
{
public RelayCommand AnimateCommand
{
get; set;
}
public AppView1Model()
{
AnimateCommand = new RelayCommand(() =>
{
Messenger.Default.Send<string>("", MessageToken.AnimateMessageToken);
});
}
}
当然,动画还是使用Blend编写要舒服一些。有了Messenger,使得ViewModel和ViewModel之间一定的
解耦,可以处理更复杂的情况。
Messenger的更多相关文章
- android:使用Messenger进行进程间通信(一)
Messenger简介 Messenger和AIDL是实现进程间通信(interprocess communication)的两种方式. 实际上,Messenger的实现其实是对AIDL的封装. Me ...
- Android进程间通讯之messenger
这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...
- android 史上最简单易懂的跨进程通讯(Messenger)!
不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...
- android:使用Messenger进行进程间通信(二)
//继续完善音乐播放器demo 相关文章: android:使用Messenger进行进程间通信(一):http://www.cnblogs.com/happyhacking/p/5318418.ht ...
- How secure FB Messenger is?
It's reported that FB Messenge is the most secure App for instant messaging service. Let's see if FB ...
- Android进程间的通信之Messenger
Android进程间的通信方式可以通过以下两种方式完成: Android接口定义语言(AIDL) 使用Messenger绑定服务 本文我们将学习使用Messenger绑定服务的方式进行进程间的通信. ...
- Android IPC机制之Messenger
Messenger:两个进程通过Messenger传递消息,进程1和进程2中都需要创建一个Messenger,创建过程:首先进程2需要创建一个服务, 并在服务中创建一个Messenger对象,进程1通 ...
- Facebook Messenger的后台架构是什么样的?
后台的架构是由前台的需求决定的.做 mobile app 的需求跟做 web app 是不一样的,比如 mobile app 对实时性的要求比较强(移动用户都没耐性),移动设备网络不稳定(要能做到断点 ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger
Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...
随机推荐
- 每日Scrum(1)
今天又正式开始了第二个冲刺周期,计划七天,主要需要改进的地方包括UI界面,还有一些细节的把握. 今天出现的主要问题有:在讨论UI界面风格的时候,小组内部意见不统一,对UI界面的创作流程不熟悉,以及难度 ...
- Puppet权威指南
<Puppet权威指南>基本信息作者: 王冬生 丛书名: Linux/Unix技术丛书出版社:机械工业出版社ISBN:9787111485988上架时间:2014-12-25出版日期:20 ...
- Sql Server之旅——第十四站 深入的探讨锁机制
上一篇我只是做了一个堆表让大家初步的认识到锁的痉挛状态,但是在现实世界上并没有这么简单的事情,起码我的表不会没有索引对吧,,,还 有就是我的表一定会有很多的连接过来,10:1的读写,很多码农可能都会遇 ...
- 使用Source Safe for SQL Server解决数据库版本管理问题(转载)
简介 在软件开发过程中,版本控制是一个广为人知的概念.因为一个项目可能会需要不同角色人员的参与,通过使用版本控制软件,可以使得项目中不同角色的人并行参与到项目当中.源代码控制使得代码可以存在多个版本, ...
- 遍历map的常用方法
Map< String, String> map = new HashMap<String, String>(); map.put("a", " ...
- SQLServer复合查询条件(AND,OR,NOT)对NULL值的处理方法
在SQL的3值逻辑下,一个查询条件可以产生以下三种情况:TRUE,FALSE,NULL.只有那些满足WHERE子句的值是TRUE的记录才出现在结果表中. NULL值影响查询条件的结果,并且结果很微妙. ...
- 安装了SQL2005再安装SQL 2008R2,提示此计算机上安装了 Microsoft Visual Studio 2008 的早期版本和检查是否安装了 SQL Server 2005 Express 工具的解决方案
工作电脑上安装了SQL 2005, 但是客户电脑上安装的是SQL 2008R2,有时候连接他们的库调试没法连接,很不方便.然后又安装了个SQL2008 R2,期间遇到这两个问题,网上搜索了一下收到了解 ...
- js相对路径相关(比如:js中的路径依赖导入该js文件的路径)
问题描述: 前几天调用同事的js接口文件,在他自己的html测试页面ok,在我这边调用时出现问题. debug过程中,将该测试html移到其他位置都不行,放到原html测试页面同层次路径下是OK的. ...
- Javascript Function()中的降龙十八掌
原文地址:http://tutorialzine.com/2014/08/what-does-this-function-do/ 下面列出十八个JS function,看你知道这些函数是干嘛用的,你能 ...
- tomcat常用配置
一. 增加内存,防止JVM内存溢出 1. 以服务的方式启动时 进入"tomcat安装路径\bin"目录下,打开service.bat文件,找到"--JvmOptions ...