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="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>
后台的代碼如下:
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());
}
}
}
需要說明一下的是,子窗體一定要先顯示,然后才能夠拋出事件,否則會因為子窗體無法接收事件而導致父窗體拋出的事件丟失。運行效果如下:
父窗體輸入:

子窗體接收:

具體的就說到這里了,后續有新的應用,會繼續更新。
源碼下載
點擊這里下載