EventAggregator简介

EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非常方便的来管理事件。下面的图就是其实现的一个比较简便的说明:

下面就以一个比较简单的例子来说明其用法,这里我们就在WPF的一个页面上输入用户信息,然后通过点击按钮,让用户信息在同一个页面上输出。

EventAggregator单页传递数据

首先,新建一个WPF项目,然后安装好Prism,这里我们可以通过程序包管理器控制台安装,待到都安装好以后,我们就可以开始使用了。

其次,创建一个GetInputMessages的类,继承自CompositePresentationEvent<string>方法,由于我们传递的都是String类型的数据,所以这里我采用String类型。这个类不提供任何实现,只需要继承就好了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Events; namespace EventAggregatorPratice
{
/// <summary>
/// 自定义的事件,一定要继承自CompositePresentationEvent类,不做任何实现
/// </summary>
public class GetInputMessages:CompositePresentationEvent<string>
{
}
}

然后,创建EventAggregatorRepository类,这个类主要存储eventAggregator对象并保证其唯一:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Events; namespace EventAggregatorPratice
{
public class EventAggregatorRepository
{
public EventAggregatorRepository()
{
eventAggregator = new EventAggregator();
} public IEventAggregator eventAggregator;
public static EventAggregatorRepository eventRepository = null; //单例,保持内存唯一实例
public static EventAggregatorRepository GetInstance()
{
if (eventRepository == null)
{
eventRepository = new EventAggregatorRepository();
}
return eventRepository;
}
}
}

最后则是创建EventAggregatorWindow.xaml窗体,然后编写窗体代码:

前台的XAML代码如下:

EventAggregatorWindow.xaml前台布局文件<Window x:Class="EventAggregatorPratice.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="测试Event Aggregator的使用方法" Height="" Width="" WindowStartupLocation="CenterScreen" >
<Grid>
<Button Content="获取输入" Height="" HorizontalAlignment="Right" Margin="0,291,53,0" Name="button1" VerticalAlignment="Top" Width="" Click="button1_Click" />
<GroupBox Header="用户信息" Height="" HorizontalAlignment="Left" Margin="12,12,0,0" Name="groupBox1" VerticalAlignment="Top" Width="">
<Grid>
<Label Content="用户昵称:" Height="" HorizontalAlignment="Left" Margin="19,18,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="用户性别:" Height="" HorizontalAlignment="Left" Margin="19,52,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="用户住址:" Height="" HorizontalAlignment="Left" Margin="19,86,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="用户年龄:" Height="" HorizontalAlignment="Left" Margin="205,18,0,0" Name="label4" VerticalAlignment="Top" />
<Label Content="用户电话:" Height="" HorizontalAlignment="Left" Margin="205,52,0,0" Name="label5" VerticalAlignment="Top" />
<TextBox Height="" HorizontalAlignment="Left" Margin="79,20,0,0" Name="txtNick" VerticalAlignment="Top" Width="" TabIndex="" />
<TextBox Height="" HorizontalAlignment="Left" Margin="269,54,0,0" Name="txtTel" VerticalAlignment="Top" Width="" TabIndex="" />
<TextBox Height="" HorizontalAlignment="Left" Margin="79,54,0,0" Name="txtSex" VerticalAlignment="Top" Width="" TabIndex="" />
<TextBox Height="" HorizontalAlignment="Left" Margin="269,20,0,0" Name="txtAge" VerticalAlignment="Top" Width="" TabIndex="" />
<TextBox Height="" HorizontalAlignment="Left" Margin="79,88,0,0" Name="txtAddress" VerticalAlignment="Top" Width="" />
<Border BorderBrush="Black" BorderThickness="" Height="" HorizontalAlignment="Left" Margin="6,117,0,0" Name="border1" VerticalAlignment="Top" Width="" />
<Label Content="获取输入:" Height="" HorizontalAlignment="Left" Margin="19,124,0,0" Name="label6" VerticalAlignment="Top" />
<TextBlock Height="" HorizontalAlignment="Left" Margin="79,124,0,0" Name="txtResult" Text="" VerticalAlignment="Top" Width="" Background="#FFF2F2F2" />
</Grid>
</GroupBox>
</Grid>
</Window>

后台的代码如下:

EventAggregatorWindow后台代码using System.Windows;
using Microsoft.Practices.Prism.Events;
using System.Text;
using System; namespace EventAggregatorPratice
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//订阅事件,一旦有事件引发,将会在这里接住
SetSubscribe();
} public void SetPublish(string messageData)
{
EventAggregatorRepository
.GetInstance()
.eventAggregator
.GetEvent<GetInputMessages>()
.Publish(messageData);
} public void SetSubscribe()
{
EventAggregatorRepository
.GetInstance()
.eventAggregator
.GetEvent<GetInputMessages>()
.Subscribe(ReceiveMessage,ThreadOption.UIThread,true);
} public void ReceiveMessage(string messageData)
{
this.txtResult.Text = messageData;
} private void button1_Click(object sender, RoutedEventArgs e)
{
//抛出事件
StringBuilder strBuilder = new StringBuilder();
strBuilder.Append("用户昵称:").Append(txtNick.Text).Append(Environment.NewLine);
strBuilder.Append("用户年龄:").Append(txtAge.Text).Append(Environment.NewLine);
strBuilder.Append("用户性别:").Append(txtSex.Text).Append(Environment.NewLine);
strBuilder.Append("用户电话:").Append(txtTel.Text).Append(Environment.NewLine);
strBuilder.Append("用户住址:").Append(txtAddress.Text).Append(Environment.NewLine);
SetPublish(strBuilder.ToString());
}
}
}

在这里,我来做一下解释:

首先,程序先通过SetSubscribe方法来订阅事件,一旦有事件抛出的时候,SetSubscribe便会利用其ReceiveMessage回调方法处理接收到的事件。

其次,当我们点击按钮的时候,一个SetPublish事件就被抛出了,并且会被SetSubscribe事件接住。效果如图:

其实现流程就如我上图中画的一样,如果你还是不很明白,我们可以利用C#中常见的Delegate来说明。

创建一个DelegateWindow.xaml窗体,窗体的前台代码与上面的一致,后台代码如下:

DelegateWindow后台代码using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes; namespace EventAggregatorPratice
{
public delegate void ValueTransferDelegate(string value); public partial class DelegateWindow : Window
{
public DelegateWindow()
{
InitializeComponent(); //事件注册,一旦检测到有事件抛出,这里就会接住
publishEvent += (string value) =>
{
txtResult.Text = value;
};
} public event ValueTransferDelegate publishEvent; //声明代理的事件 private void button1_Click(object sender, RoutedEventArgs e)
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.Append("用户昵称:").Append(txtNick.Text).Append(Environment.NewLine);
strBuilder.Append("用户年龄:").Append(txtAge.Text).Append(Environment.NewLine);
strBuilder.Append("用户性别:").Append(txtSex.Text).Append(Environment.NewLine);
strBuilder.Append("用户电话:").Append(txtTel.Text).Append(Environment.NewLine);
strBuilder.Append("用户住址:").Append(txtAddress.Text).Append(Environment.NewLine); if (publishEvent != null)
publishEvent(strBuilder.ToString()); //事件抛出
}
}
}

在窗体Init的时候,我们注册了回调事件:

//事件注册,一旦检测到有事件抛出,这里就会接住
publishEvent += (string value) =>
{
txtResult.Text = value;
};

这段代码就类似于上面的SetSubscribe()方法,都是为了注册回调事件,以便于处理接收到的信息。

然后在点击按钮的时候,我们将事件抛出:

 if (publishEvent != null)
publishEvent(strBuilder.ToString()); //事件抛出

这段代码就类似于上面的SetPublish(strBuilder.ToString())方法,用于抛出事件.

所以,看到这里,你是不是已经非常的清楚明了了呢?请看效果图:

EventAggregator向子页面传递数据

上面说到的都是单一窗体传值的情况,如果要是传值给子窗体,该如何设计呢?其实,使用方法和上面的示例类似,只不过需要弹出子窗体而已。

首先,在子窗体FormPostUsingEventAggregatorChild.xaml中,我们由于要接收父窗体传入的值,所以这里应该利用SetSubscribe方法来处理回调事件:

using System.Windows;

namespace EventAggregatorPratice
{
public partial class FormPostUsingEventAggregatorChild : Window
{
public FormPostUsingEventAggregatorChild()
{
InitializeComponent();
SetSubscribe();
}
public void SetSubscribe()
{
EventAggregatorRepository
.GetInstance()
.eventAggregator
.GetEvent<GetInputMessages>()
.Subscribe((message) =>
{
txtResult.Text = message;
});
}
}
}

而在父窗体FormPostUsingEventAggregator.xaml中,由于要抛出事件,所以我们只需要利用SetPublish抛出事件即可。

using System;
using System.Text;
using System.Windows; namespace EventAggregatorPratice
{
public partial class FormPostUsingEventAggregator : Window
{
public FormPostUsingEventAggregator()
{
InitializeComponent();
} public void SetPublish(string message)
{
EventAggregatorRepository
.GetInstance()
.eventAggregator
.GetEvent<GetInputMessages>()
.Publish(message);
} private void button1_Click(object sender, RoutedEventArgs e)
{
//先实例化子窗体
FormPostUsingEventAggregatorChild child = new FormPostUsingEventAggregatorChild();
child.Show(); //然后抛出事件
StringBuilder strBuilder = new StringBuilder();
strBuilder.Append("用户昵称:").Append(txtNick.Text).Append(Environment.NewLine);
strBuilder.Append("用户年龄:").Append(txtAge.Text).Append(Environment.NewLine);
strBuilder.Append("用户性别:").Append(txtSex.Text).Append(Environment.NewLine);
strBuilder.Append("用户电话:").Append(txtTel.Text).Append(Environment.NewLine);
strBuilder.Append("用户住址:").Append(txtAddress.Text).Append(Environment.NewLine);
SetPublish(strBuilder.ToString());
}
}
}

需要说明一下的是,子窗体一定要先显示,然后才能够抛出事件,否则会因为子窗体无法接收事件而导致父窗体抛出的事件丢失。运行效果如下:

父窗体输入:

子窗体接收:

具体的就说到这里了,后续有新的应用,会继续更新。

源码下载

点击这里下载

 
 

基于EventAggregator的事件发布及订阅的更多相关文章

  1. WPF EventAggregator(基于EventAggregator的事件发布及订阅)

    一.EventAggregator简介 EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非 ...

  2. Dapr实现.Net Grpc服务之间的发布和订阅,并采用WebApi类似的事件订阅方式

    大家好,我是失业在家,正在找工作的博主Jerry,找工作之余,总结和整理以前的项目经验,动手写了个洋葱架构(整洁架构)示例解决方案 OnionArch.其目的是为了更好的实现基于DDD(领域驱动分析) ...

  3. 模块(类)之间解耦利器:EventPublishSubscribeUtils 事件发布订阅工具类

    如果熟悉C#语言的小伙伴们一般都会知道委托.事件的好处,只需在某个类中提前定义好公开的委托或事件(委托的特殊表现形式)变量,然后在其它类中就可以很随意的订阅该委托或事件,当委托或事件被触发执行时,会自 ...

  4. 使用MediatR重构单体应用中的事件发布/订阅

    标题:使用MediatR重构单体应用中的事件发布/订阅 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10640280.html 源代码:https ...

  5. ASP.NET Core中实现单体程序的事件发布/订阅

    标题:ASP.NET Core中实现单体程序的事件发布/订阅 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10468058.html 项目源代码: ...

  6. WPF的EventAggregator的发布和订阅

    EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非常方便的来管理事件.下面分几步来实现相关 ...

  7. guava的事件发布订阅功能

    事件的重要性,不用说很重要,在很多时候我们做完一个操作的时候,需要告知另外一个对象让他执行相应操作,比如当用户注册成功的时候,需要抛出一个注册成功的事件,那么有监听器捕获到这个事件,完成后续用户信息初 ...

  8. Blazor+Dapr+K8s微服务之事件发布订阅

    我们要实现的是:在blazorweb服务中发布一个事件,并传递事件参数,然后在serviceapi1服务中订阅该事件,接收到blazorweb服务中发布的事件和参数. 1         在blazo ...

  9. spring#事件发布订阅

    1. 如果在应用中发生了某些事件,事件会被拦截和处理就好了,这样就有了很大的灵活性,至少代码不会紧密的耦合在一起, 代码的解耦就是业务的解耦,业务A的代码不用手动的调用业务B的代码,业务B只需要监听相 ...

随机推荐

  1. IOS之未解问题--关于IOS图像渲染CPU和GPU

    前言:先上一个图.关于UIKit底层渲染机制,这个有待以后花大把时间收集资料和学习,然后汇总,将整篇"未解问题"去除. 反思:半个月前阿里电话面试,问道一个问题图像渲染什么时候回用 ...

  2. Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver

    Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver 报错信息:

  3. JavaScript Patterns 2.12 Writing API Docs

    Free and open source tools for doc generation: the JSDoc Toolkit (http://code.google.com/p/jsdoc-too ...

  4. Android Listener侦听的N种写法

    Android中,View的Listener方法,在是否使用匿名类匿名对象时,有各种不同的写法. OnClickListener和其他Listener方法一样,都是View类的接口,重载实现后就能使用 ...

  5. 排序(qsort sort的使用)

    前情:因平常写代码是常将比较函数弄混(写好了排序还要确认一下-.-!),还是写篇博客,方便以后查阅 C语言qsort函数对int类型数组排序: #include "stdio.h" ...

  6. 树形dp--hdu 3534 Tree

    Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  7. Kafka原理与java simple producer示例

    brokers和消费者使用zk来获取状态信息和追踪消息坐标. 每一个partition是一个有序的,不可变的消息序列. 只有当partition里面的file置换到磁盘文件以后,才开放给消费者来消费. ...

  8. FPGA 设计技巧

    1.  资源共享的应用限制在同一个module里 这样 综合工具才能最大限度地发挥其资源共 享综合作用 2.  尽可能将Critical path上所有相关逻辑放在同一个module里 这样 综合工具 ...

  9. ASP.NET MVC中分析淘宝网页发生乱码标题搞定方法

    ASP.NET MVC中分析淘宝网页发生乱码标题搞定方法 近来正在分析淘宝中商品的信息,效果发生乱码,如: 原因便是中文字符格式发生冲突,ASP.NET MVC 默认采用utf-8,可是淘宝网页采用g ...

  10. 二叉树结构 codevs 1029 遍历问题

    codevs 1029 遍历问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 我们都很熟悉二叉树的前序.中序.后序遍 ...