Decoupled Communication with Prism (Event Aggregation)

In my previous post, I discussed commanding and how you can hook up invokers (e.g. buttons and menu items), global CompositeCommands, and module level command instances. If you need the sending of a message to be initiated by a user gesture such as a button click, Commands may be a good choice. If you need the sending of a message to be initiated by business logic code, such as in a controller or presenter, you should consider using the EventAggregator.

In the case where a button has been clicked, validation has passed, and work has been completed, it is often useful to alert the rest of the application that this event has occurred. Let's say the the "Process Order" button has been pressed. If the order is successfully processed, other modules may want to know so that they can update their views: "Processed Orders List", "Pending Orders List", "Available Inventory"... For this type of communication, we developed EventAggregator.

EventAggregator provides multicast publish/subscribe functionality. There can be multiple publishers that publish/fire/raise the same event and there can be many subscribers who listen to the same event. If you define the event in a common assembly, EventAggregator can be used across module assemblies.

Defining an event:

Defining an EventAggregator event is as simple as extending WpfEvent<TPayload> supplying the payload type.

 public class TickerSymbolSelectedEvent : WpfEvent<string> { }

For the TickerSymbolSelectedEvent, publishers will need to provide a string argument, and subscribers can expect to receive a string argument.

EventAggregator Singleton Service:

Make sure that the EventAggregator instance is treated as a singleton. One way to do this is to register this type in your dependency injection container as a single instance and always use the container to resolve the EventAggregator.

 unityContainer.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());

The EventAggregator is merely a singleton factory. When you call its GetEvent<TEventType> method, it will return an instance of TEventType that was previously requested, or create a new instance and keep track of it.

Publishing an event:

Use the singleton instance of the EventAggregator to get an instance of the event to which you want to work with. Call the event's Publish method supplying the message payload. The WpfEvent<TPayload> base class manages all the subscriptions and handles cross thread messaging.


Subscribing to an event:

Again, use the singleton instance of EventAggregator to get an instance of the event to which you want to work with. Call the event's Subscribe method supplying a delegate to handle the receiving of the message. You can optionally provide a ThreadOption to specify which thread on which you would like to receive the message (publisher's thread, UI thread, or background thread). You can optionally provide a boolean to specify whether or not to provide a strong reference to the subscriber. This defaults to false so that the subscriber can be garbage collected even though it did not unregister to our EventAggregator event. Finally you can optionally provide a predicate delegate to filter the messages based on your custom criteria. Please note that you can only filter on properties of the message payload.

 eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Subscribe(ShowNews, ThreadOption.UIThread);