WPF MVVM Stylet使用文档(中文)08-The EventAggregator
简介
事件聚合器——EventAggregator——是一个分散的、弱绑定的、基于发布/订阅的事件管理器。
发布者和订阅者(Publishers and Subscribers)
订阅者(Subscribers)
对特定事件感兴趣的订阅者可以将自己的兴趣告诉 IEventAggregator,并且每当发布者将特定事件发布到IEventAggregator 时,都会收到通知。
事件是类——可以用它们做任何你想做的事情。例如:
C# | VB.NET |
class MyEvent {
// Do something
}
|
Class MyEvent
' Do Something
End Class
|
订阅者必须实现 IHandle<T>
,其中 T
是他们感兴趣的事件类型 (当然,他们可以实现多个
IHandle<T>
's for多个 T
's)。然后他们必须获得 IEventAggregator 的实例,并订阅自己,例如:
C# | VB.NET |
class Subscriber : IHandle<MyEvent>, IHandle<MyOtherEvent>
{
public Subscriber(IEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this);
}
public void Handle(MyEvent message)
{
// ...
}
public void Handle(MyOtherEvent message)
{
// ...
}
}
|
Class Subscriber : Implements IHandle(Of MyEvent)
Public Sub New(ByRef eventAggregator as IEventAggregator)
eventAggregator.Subscribe(Me)
End Sub
Public Sub Handle(message as MyEvent) Implements IHandle(Of MyEvent).Handle
' ...
End Sub
Public Sub Handle(message as MyOtherEvent) Implements IHandle(Of MyOtherEvent).Handle
' ...
End Sub
End Class
|
VB.NET 用户,通过引用传递 eventAggregator 的 Sub New()
在跨命名空间时可能会失败,而且必须定义每个新订阅者,这可能会令人恼火。因此,在全局模块中定义eventAggregator,然后直接订阅它,而不是将其引用传递给调用的每个新
ViewModel,可能更容易。
1 | Module Global |
确保将 module 的名称空间保留为空,以便可以在整个程序中使用它。
发布者(Publishers)
发布者也必须获得 IEventAggregator
的实例,但他们不需要订阅自己—只需在每次发布想要发布的事件时调用
IEventAggregator.Publish
,例如:
C# | VB.NET |
class Publisher
{
private IEventAggregator eventAggregator;
public Publisher(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public void PublishEvent()
{
this.eventAggregator.Publish(new MyEvent());
}
}
|
Class Publisher
Dim eventAggregator as IEventAggregator
Public Sub New(ByRef eventAggregator as IEventAggregator)
Me.eventAggregator = eventAggregator
End Sub
Public Sub PublishEvent()
Me.eventAggregator.Publish(New MyEvent())
End Sub
End Class
|
再次,VB.NET用户,如果您已经设置了全局模块,那么您不需要将 eventAggregator 传递给发布者。你可以直接发布到全局事件聚合器:
1 | Class Publisher |
取消订阅和弱绑定(UnSubscribing adn weak binding)
因为 IEventAggregator 是弱绑定的,订阅者不需要取消订阅— IEventAggregator 不会保留它们。但是,如果订阅者想要取消订阅,也可以取消订阅。如下:
C# | VB.NET |
IEventAggregator.Unsubscribe(this);
|
IEventAggregator.UnSubscribe(Me)
|
同步和异步发布(Publishing synchronously and asynchronously)
默认的 IEventAggregator.Publish
方法是同步发布事件。您还可以调用 PublishOnUIThread
来异步地调度UI 线程,或者调用
PublishWithDispatcher
,并传递您希望充当 dispatcher
的任何操作(如果在IEventAggregator上编写自己的方法,这将非常有用)。
频道(Channels)
订阅者可以侦听特定的频道,发布者可以将事件发布到特定的频道。如果将事件发布到特定的频道,则只有已订阅该频道的订阅者才能接收该事件。如果在几个不同的上下文中使用相同的消息类型,那么这将非常有用。
频道是字符串,因此允许一个频道的订阅者和该频道的发布者之间的松散耦合。
默认情况下,Subscribe()
将订阅方订阅到默认频道
EventAggregator.DefaultChannel
。类似地,
Publish()
(及其所有变体)
将把事件发布到相同的默认频道。然而,你也可以指定自己的频道。
订阅到频道(Subscribing to channels)
若要订阅特定频道,请将其作为参数传递给 subscribe”
:
eventAggregator.Subscribe(this,“ChannelA”)
。你也可以订阅多个频道:
eventAggregator.Subscribe(this,“ChannelA”,“ChannelB”)
。
在这两种情况下,你都不会订阅到
EventAggregator.DefaultChannel
-只订阅到指定的频道。你也只会收到被推送至“ChannelA”或“ChannelB”的事件。
发布到频道(Publishing to channels)
若要发布到特定通道,请将其作为参数传递给publish
:
eventAggregator.Publish(message,“ChannelA”)
或
eventAggregator.PublishOnUIThread(message,“ChannelA”,“ChannelB”)
,等等。与上面的订阅一样,事件将发布到所有指定的通道,而不再是默认通道。
从频道取消订阅(Unsubscribing from channels)
要取消频道订阅,请将其传递给 Unsubscribe
:
eventAggregator.Unsubscribe(this, "ChannelA")
。您将继续订阅您以前订阅的且没有取消订阅的任何其他频道。
调用 eventAggregator.Unsubscribe(this)
将从所有
频道取消订阅。
使用自己的 IoC 容器(Using your own IoC container)
如果你在 StyletIoC 中使用默认的
Bootstrapper<TRootViewModel>
,你不需要担心这个——EventAggregator
在默认情况下是正确设置的。
如果你使用另一个 IoC 容器,那么,你需要确保 EventAggregator 注册为 IEventAggregator 的独立服务, EventAggregator 只能有一个实例,每次请求的时候,都必须返回这个实例。