EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非常方便的来管理事件。下面的图就是其实现的一个比较简便的说明
EventAggregator简介
EventAggregator是Prism中专门处理ViewModel与ViewModel之间事件传递的类对象,它提供了针对事件的发布方法和订阅方法,所以可以非常方便的来管理事件。下面的图就是其实现的一个比较简便的说明:
![QQ截图20131105092632 QQ截图20131105092632](//images0.cnblogs.com/blog/47012/201311/05100612-7c60906d87f24049bba98389d72dec76.png)
下面就以一个比较简单的例子来说明其用法,这里我们就在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代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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="365" Width="471" WindowStartupLocation="CenterScreen" >
<Grid>
<Button Content="获取输入" Height="23" HorizontalAlignment="Right" Margin="0,291,53,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<GroupBox Header="用户信息" Height="273" HorizontalAlignment="Left" Margin="12,12,0,0" Name="groupBox1" VerticalAlignment="Top" Width="425">
<Grid>
<Label Content="用户昵称:" Height="28" HorizontalAlignment="Left" Margin="19,18,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="用户性别:" Height="28" HorizontalAlignment="Left" Margin="19,52,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="用户住址:" Height="28" HorizontalAlignment="Left" Margin="19,86,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="用户年龄:" Height="28" HorizontalAlignment="Left" Margin="205,18,0,0" Name="label4" VerticalAlignment="Top" />
<Label Content="用户电话:" Height="28" HorizontalAlignment="Left" Margin="205,52,0,0" Name="label5" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="79,20,0,0" Name="txtNick" VerticalAlignment="Top" Width="109" TabIndex="1" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="269,54,0,0" Name="txtTel" VerticalAlignment="Top" Width="109" TabIndex="4" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="79,54,0,0" Name="txtSex" VerticalAlignment="Top" Width="109" TabIndex="3" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="269,20,0,0" Name="txtAge" VerticalAlignment="Top" Width="109" TabIndex="2" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="79,88,0,0" Name="txtAddress" VerticalAlignment="Top" Width="299" />
<Border BorderBrush="Black" BorderThickness="1" Height="1" HorizontalAlignment="Left" Margin="6,117,0,0" Name="border1" VerticalAlignment="Top" Width="401" />
<Label Content="获取输入:" Height="28" HorizontalAlignment="Left" Margin="19,124,0,0" Name="label6" VerticalAlignment="Top" />
<TextBlock Height="124" HorizontalAlignment="Left" Margin="79,124,0,0" Name="txtResult" Text="" VerticalAlignment="Top" Width="299" Background="#FFF2F2F2" />
</Grid>
</GroupBox>
</Grid>
</Window>
后台的代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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事件接住。效果如图:
![QQ截图20131105094820 QQ截图20131105094820](//images0.cnblogs.com/blog/47012/201311/05100617-7ff82555600f43de8218b5891c93729d.png)
其实现流程就如我上图中画的一样,如果你还是不很明白,我们可以利用C#中常见的Delegate来说明。
创建一个DelegateWindow.xaml窗体,窗体的前台代码与上面的一致,后台代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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())方法,用于抛出事件.
所以,看到这里,你是不是已经非常的清楚明了了呢?请看效果图:
![QQ截图20131105095656 QQ截图20131105095656](//images0.cnblogs.com/blog/47012/201311/05100619-3a17526bf7174aa3a1d20c8a51fc55eb.png)
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());
}
}
}
需要说明一下的是,子窗体一定要先显示,然后才能够抛出事件,否则会因为子窗体无法接收事件而导致父窗体抛出的事件丢失。运行效果如下:
父窗体输入:
![QQ截图201311051003061 QQ截图201311051003061](//images0.cnblogs.com/blog/47012/201311/05100625-491dc4fd234e4c3dbced4a9ab09e68ef.png)
子窗体接收:
![QQ截图201311051003112 QQ截图201311051003112](//images0.cnblogs.com/blog/47012/201311/05100630-d6a05becc08746458ffb98f749d773d4.png)
具体的就说到这里了,后续有新的应用,会继续更新。
源码下载
点击这里下载