在本篇文章中主要讲解在Prism中模块与模块之间事件关联的机制。在这里牵涉到三个名词:事件定义,事件发布,事件订阅。
第一:事件定义
在公共类库中定义事件。
①没有参数事件
public class NullClass { }
public class NullableEvent : CompositePresentationEvent<NullClass> { }
②简单类型参数事件
public class MessageAddedEvent : CompositePresentationEvent<string> { }
③复合类型参数事件
public class News
{
/// <summary>
/// 标题。
/// </summary>
public string Title { get; set; }
/// <summary>
/// 内容。
/// </summary>
public string Content { get; set; }
}
public class NewsAddedEvent : CompositePresentationEvent<News> { }
第二:事件发布(以下为示例代码)
using Microsoft.Practices.Composite.Events;
using PrismEvent.Infrastructure;
using System.Windows;
using System.Windows.Controls; namespace PrismEvent.Publisher
{
/// <summary>
/// PublisherView.xaml 的交互逻辑
/// </summary>
public partial class PublisherView : UserControl
{
IEventAggregator eventAggregator;
/// <summary>
/// 构造函数。
/// </summary>
public PublisherView()
{
InitializeComponent();
}
/// <summary>
/// 构造函数。
/// </summary>
/// <param name="eventAggregator">事件聚合。</param>
public PublisherView(IEventAggregator eventAggregator)
: this()
{
this.eventAggregator = eventAggregator;
}
/// <summary>
/// 简单参数。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSimpleParam_Click(object sender, RoutedEventArgs e)
{
string message = "Hellow world";
eventAggregator.GetEvent<MessageAddedEvent>().Publish(message);
}
/// <summary>
/// 复合参数。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCompositeParam_Click(object sender, RoutedEventArgs e)
{
News news = new News()
{
Title = "Bao's demo was published.",
Content = "This message is wonderful."
};
eventAggregator.GetEvent<NewsAddedEvent>().Publish(news);
} private void btnWithoutParam_Click(object sender, RoutedEventArgs e)
{
eventAggregator.GetEvent<NullableEvent>().Publish(null);
} private void btnStandard_Click(object sender, RoutedEventArgs e)
{
string message = "Open seasame!";
eventAggregator.GetEvent<StandardMessageAddedEvent>().Publish(message);
}
}
}
第三:事件订阅
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
using PrismEvent.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Navigation;
using System.Windows.Shapes; namespace PrismEvent.Subscriber
{
/// <summary>
/// Subscriberview.xaml 的交互逻辑
/// </summary>
public partial class Subscriberview : UserControl
{
IEventAggregator eventAggregator;
private SubscriptionToken subscriptionToken;
public Subscriberview()
{
InitializeComponent();
} public Subscriberview(IEventAggregator eventAggregator)
: this()
{
this.eventAggregator = eventAggregator;
this.eventAggregator.GetEvent<MessageAddedEvent>().Subscribe(ShowMessage);
this.eventAggregator.GetEvent<NewsAddedEvent>().Subscribe(ShowMessage);
this.eventAggregator.GetEvent<NullableEvent>().Subscribe(DoSomething);
StandardMessageAddedEvent messageAddedEvent = eventAggregator.GetEvent<StandardMessageAddedEvent>();
if (subscriptionToken != null)
{
messageAddedEvent.Unsubscribe(subscriptionToken);
}
subscriptionToken = messageAddedEvent.Subscribe(ShowMessage2, ThreadOption.UIThread, true, Filter);
} private bool Filter(string message)
{
return true;
} private void ShowMessage2(string message)
{
this.tbSimpleParam.Text = message;
StandardMessageAddedEvent messageAddedEvent = eventAggregator.GetEvent<StandardMessageAddedEvent>();
if (subscriptionToken != null)
{
messageAddedEvent.Unsubscribe(subscriptionToken);
}
} private void DoSomething(NullClass obj)
{ }
/// <summary>
/// 显示新闻消息。
/// </summary>
/// <param name="news">新闻对象。</param>
private void ShowMessage(News news)
{
this.tbSimpleParam.Text = news.Title;
}
/// <summary>
/// 显示消息。
/// </summary>
/// <param name="message">消息内容。</param>
private void ShowMessage(string message)
{
this.tbSimpleParam.Text = message;
} }
}
对于事件的订阅,正规的写法如下所示:
StandardMessageAddedEvent messageAddedEvent = eventAggregator.GetEvent<StandardMessageAddedEvent>(); if (subscriptionToken != null) { messageAddedEvent.Unsubscribe(subscriptionToken); } subscriptionToken = messageAddedEvent.Subscribe(ShowMessage2, ThreadOption.UIThread, true, Filter);
在上面的代码中,我们看到这样的顺序:
1.先从IEventAggregator中获取注册到其中的事件对象,也就是messageAddedEvent;
StandardMessageAddedEvent messageAddedEvent=eventAggregator.GetEvent<StandardMessageAddedEvent>();
2.这个messageAddedEvent对象具有Subscribe方法,它返回一个SubscriptionToken类型的对象,用来标志事件触发后,在订阅一方所调用的方法:
subscriptionToken=messageAddedEvent.Subscribe(ShowMessage2,ThreadOption.UIThread,true,Filter);
3.在第2步之前,我们需要检查SubscriptionToken对象是否为空,否则就要注销之前的messageAddedEventHandler方法。
if(subscriptionToken!=null)
{
messageAddedEvnet.Unsubscribe(subscriptionToken);
}
之所以这么写,是因为系统弱引用后的垃圾自动回收时间,于是,将Subscribe方法的第三个参数设置为true(默认为false,弱引用,垃圾自动回收)。这样,订阅的就是强引用了,Prism就会要求我们必须手动取消事件的订阅。
在Subscribe方法中,第二个参数是ThreadOption枚举。值有:
publisherThread //在publisherThread所在线程上执行,默认值。
UIThread //在UI线程上触发。
BackgroundThread //在后台线程上异步调用。
第四个参数是一个bool类型的委托,它以事件传递的消息类型作为参数。
subscriptionToken=messageAddedEvent.Subscribe(ShowMessage2,ThreadOption.UIThread,true,Filter);
public bool Filter(string text){
return true;
}
注意:Filter方法总会在ShowMessage2方法前执行。如果返回true,则执行ShowMessage2。若为false则不执行。
在此,Prism的事件机制告一段落。