从PRISM开始学WPF(六)MVVM(三)事件聚合器EventAggregator?
事件聚合器EventAggregator
[7.1updated]除了app部分,没有任何变化
- Event aggregation. For communication across view models, presenters, or controllers when there is not a direct action-reaction expectation.
(⊙﹏⊙),Google一下:
事件聚合。在没有直接的行动反应期望的情况下,跨视图模型,演示者或控制者进行通信。
1是没有直接行动反应期望,2跨视图通信
在具体了解这个概念之前,先看一个例子:
通过简介,很容易想到聊天窗口,当你在一个视图A中输入文字点击发送之后,另外一个视图B会接收到这个消息,并将文字输出到屏幕上,而这个时候,视图A并不关心谁将收到信息,只管提交,视图B也不管是谁发来的消息,只管接收,并显示。
关门,放代码:
Setp1 在Shell窗口中,定义两个Region,分别来展示发送视图和接收视图
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl prism:RegionManager.RegionName="LeftRegion" />
<ContentControl Grid.Column="1" prism:RegionManager.RegionName="RightRegion" />
</Grid>
今天Typora更新了,代码块支持
xaml格式,以前都是用xml-dtd,下面统一使用xaml
XAML这应该是教程中出现的比较复杂的xaml,比较详细的使用了Grid,这里的Grid很像一个表格,在使用他布局之前,需要定义好列数,下面的代码为Grid设置了两个列
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
那么能加行吗?那是当然的了,下面是为Grid添加两行,Height的Auto表示这个行的高度会根据内容高度进行适应:
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
在使用Grid的时候,需要为控件指定Grid的位置
Grid.Column="1",1就是下标,都是从0开始的,1就代表第二列,当你不指定具体位置的时候,默认将控件插入Grid的0行0列,上面的LeftRegion就是在首行首列的位置。
Setp2 新建两个Module,分别为ModuleA 和 ModuleB,ModuleA中的视图用来发送信息,ModuleB中的视图用来接收显示信息。
Module的创建在第四节已经说明了
先看ModuleA的发送视图:
MessageView.xaml
<StackPanel>
<TextBox Text="{Binding Message}" Margin="5"/>
<Button Command="{Binding SendMessageCommand}" Content="Send Message" Margin="5"/>
</StackPanel>
MessageView中定义了一个文本框,进行了数据绑定,然后是一个按钮,绑定了一个SendMessageCommand命令。在我们点击Send Message按钮的时候,就会将Message显示到接收视图里去。
再看ModuleB的显示视图:
MessageList.xaml
<Grid>
<ListBox ItemsSource="{Binding Messages}" />
</Grid>
就定义了一个ListBox来显示Message。ItemsSource绑定的应该是一个集合,不然怎么叫Source呢?
接下来,看下Prism怎么实现跨视图模型通讯:
首先,定义一个MessageSentEvent类,继承PubSubEvent<string>,string是因为这个事件接收的payload是字符串类型,PubSubEvent<T>类负责连接发布者和订阅者,他负责维护订阅者列表并处理事件派发给订阅者。
using Prism.Events;
namespace UsingEventAggregator.Core
{
public class MessageSentEvent : PubSubEvent<string>
{
}
}
然后我们看下MessageViewModel:
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using UsingEventAggregator.Core;
namespace ModuleA.ViewModels
{
public class MessageViewModel : BindableBase
{
IEventAggregator _ea;
private string _message = "Message to Send";
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public DelegateCommand SendMessageCommand { get; private set; }
public MessageViewModel(IEventAggregator ea)
{
_ea = ea;
SendMessageCommand = new DelegateCommand(SendMessage);
}
private void SendMessage()
{
_ea.GetEvent<MessageSentEvent>().Publish(Message);
}
}
}
先看我们熟悉的部分:
private string _message = "Message to Send";
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
这是<TextBox Text="{Binding Message}" Margin="5"/>中的Message
然后定义了一个DelegateCommand
public DelegateCommand SendMessageCommand { get; private set; }
接下来就是EventAggregator部分了:
首先定义一个IEventAggregator:
IEventAggregator _ea;
构造函数:
ea是依赖注入容器提供的EventAggregator实例,还定义了命令SendMessageCommand的回调函数SendMessage。
public MessageViewModel(IEventAggregator ea)
{
_ea = ea;
SendMessageCommand = new DelegateCommand(SendMessage);
}
SendMessge中通过MessageSentEvent发布Payload,这里Payload一定要匹配MessageSentEvent的Payload类型,上面我们继承PubSubEvent<string>时使用的String,不然的话,这在编译的时候就会抛出异常。
private void SendMessage()
{
_ea.GetEvent<MessageSentEvent>().Publish(Message);
}
接下来,我们让ModuleB中的MessageListViewModel获取这个Payload,并进行一些操作:
using Prism.Events;
using Prism.Mvvm;
using System.Collections.ObjectModel;
using UsingEventAggregator.Core;
namespace ModuleB.ViewModels
{
public class MessageListViewModel : BindableBase
{
IEventAggregator _ea;
private ObservableCollection<string> _messages;
public ObservableCollection<string> Messages
{
get { return _messages; }
set { SetProperty(ref _messages, value); }
}
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
Messages = new ObservableCollection<string>();
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);
}
private void MessageReceived(string message)
{
Messages.Add(message);
}
}
}
代码阅读:
private ObservableCollection<string> _messages;
public ObservableCollection<string> Messages
{
get { return _messages; }
set { SetProperty(ref _messages, value); }
}
这是 <ListBox ItemsSource="{Binding Messages}" /> 中的Messages,他的类型是ObservableCollection,具体为什么是 ObservableCollection而不是List!后面再说。
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
Messages = new ObservableCollection<string>();
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);
}
这里订阅了MessageSentEvent,并且处理Payload,处理Payload的方法是MessageReceived,这个方法在Messages新增一条记录。
事件聚合器可以有多个发布者和多个订阅者。
作为订阅者,我想订阅特定类型的Payload,上个例子中我只想订阅message里含有Brian的事件,怎么处理呢?Prism为Subscribe方法实现了一个过滤器:
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived, ThreadOption.PublisherThread, false, (filter) => filter.Contains("Brian"));
过滤器是一个Predicate<TPayload> filter,参考 Predicate 委托
从PRISM开始学WPF(六)MVVM(三)事件聚合器EventAggregator?的更多相关文章
- 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator?
原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WP ...
- 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1
原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1 事件聚合器EventAggregator [7.1updated]除了app部分,没 ...
- 从PRISM开始学WPF,Prism7更新了什么
当时我在搬运Prism6.3的sample代码的时候,就是因为网上的资料太老旧,万万没想到这给自己挖了一个坑,因为我在做笔记的时候,prism已经在更新7.0了 现在已经是7.2了,(lll¬ω¬), ...
- 从PRISM开始学WPF(一)WPF?
从PRISM开始学WPF(一)WPF? 我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的MVVM框架--MVVM ...
- 从PRISM开始学WPF(一)WPF-更新至Prism7.1
原文:从PRISM开始学WPF(一)WPF-更新至Prism7.1 我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的 ...
- .NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器 在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...
- 从PRISM开始学WPF(八)导航Navigation-更新至Prism7.1
原文:从PRISM开始学WPF(八)导航Navigation-更新至Prism7.1 0x6Navigation [7.1updated] Navigation 在wpf中并没有变化 Basic Na ...
- 从PRISM开始学WPF(番外)共享上下文 RegionContext?
原文:从PRISM开始学WPF(番外)共享上下文 RegionContext? RegionContext共享上下文 There are a lot of scenarios where you mi ...
- 从PRISM开始学WPF(八)导航Navigation?
原文:从PRISM开始学WPF(八)导航Navigation? 0x6Navigation Basic Navigation Prism中的Navigation提供了一种类似导航的功能,他可以根据用户 ...
随机推荐
- 【BZOJ4071】八邻旁之桥(线段树)
[BZOJ4071]八邻旁之桥(线段树) 题面 BZOJ权限题,洛谷链接 题解 既然\(k<=2\) 那么,突破口就在这里 分类讨论 ①\(k=1\) 这...不就是中位数吗.... 直接把所有 ...
- 【BZOJ1934】善意的投票(网络流)
[BZOJ1934]善意的投票(网络流) 题面 Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己 ...
- 【BZOJ1008】【HNOI2008】越狱(组合数学)
题面 题目描述 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 输入输出格式 ...
- 【HNOI2004】敲砖块(动态规划)
越来越懒了,不想粘题目 题解 样例的输入是个很好的提醒, 把他往左边对齐之后 如果要打掉某个位置,那么必须要打掉右上方的所有砖 然后就很明显的一个DP了.... #include<iostrea ...
- [BZOJ1606] [Usaco2008 Dec] Hay For Sale 购买干草 (dp)
Description 约翰遭受了重大的损失:蟑螂吃掉了他所有的干草,留下一群饥饿的牛.他乘着容量为C(1≤C≤50000)个单位的马车,去顿因家买一些干草. 顿因有H(1≤H≤5000)包干草,每 ...
- springmvc结合ajax的分页功能
var itemCount;//符合查找条件的商品总页数,分页参考 var pageIndex = 0;//当前页,默认为0 var pageSize = 8;//每页显示个数为8 //按条件查找用户 ...
- Web前端有价值的博客文章汇总
一.HTML 二.CSS 1.深入理解position和z-index属性 :https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 2.BFC(清除 ...
- 关于win系统下Anaconda与TensorFlow的安装相关事宜以及错误:ImportError: No module named 'tensorflow'的解决
1.安装TensorFlow之前应该先安装Anaconda,不需要安装python,否则会出问题,我安装的版本是Anaconda3-4.2.0-Windows-x86_64,在这个链接上可以找到--h ...
- 简单http代理服务器搭建
1. yum install squid2. vi /etc/squid/squid.conf 将http_access deny all 中deny 改为allow,http_port后面的是端口号 ...
- 用JNDI连接数据库
之前说到了利用Java中的Properties类读取properties配置文件,连接数据库,现在说另一种方法,他们的目的和作用都是一样的,都是为了提高代码的复用性,解决了更改数据库 时还要更改代码的 ...