Use eventaggregation for inter-module communication in Prism

Source: Internet
Author: User

When developing a Silverlight program, you often need to communicate between different components. For example, if you click a button, you may need to change the content of another control. The direct method is to use events. Of course, command can be used when mvvm is used, and some global variables can be defined to save some information.

Prism provides several ways for communication between components. You can use regioncontext to share data between different views, or use the power of containers to use shared services for communication, or use command. In addition, Prism also provides an event-based multicast publishing/subscription mode for communication between different components in a loosely coupled manner. This is the event aggregation described in this article ).

The process of event aggregation is a bit like listening to a broadcast. First, there must be a fixed frequency, and then the content will be broadcast on this frequency. As for whether or not anyone listens, the broadcast station does not know, it only broadcasts the content. Other people do not need to go to the radio station to listen to the broadcast. They only need to know the frequency and listen to the frequency. This frequency is used to contact radio stations and listeners.

In the process of event aggregation, the event publisher is equivalent to a broadcast station, and the event receiver (subscriber) is equivalent to a listener, and the event is naturally equivalent to a frequency.

Using Event aggregation is simple. You only need to know one interface and one class. The interface is ieventaggregator and the class is compositepresentationevent.

To publish or subscribe to events, you must first have events. Therefore, the first task is to define events. Prism provides an event base class compositepresentationevent <tpayload>. Custom events only need to inherit this class. Generics represent the parameter types that need to be passed when an event occurs. For example:

public class ReceiveNewEmailEvent : CompositePresentationEvent<MailViewModel>{}

An event is defined above for use when a new email is received. The parameter passed is the viewmodel of the email.

It is also easy to use. Use the getevent <teventtype> method in the ieventaggregator interface to obtain the event, and publish the event or subscribe to it.

The following code releases the event when receiving a new email:

Public class emailreceiver {private ieventaggregator _ eventaggregator; Public emailreceiver (ieventaggregator eventaggregator) {_ eventaggregator = eventaggregator;} public void receiveemail () {If (_ email! = NULL) {// when a new email is received, the event is published. All components that subscribe to this event will receive the notification _ eventaggregator. getevent <incluenewemailevent> (). publish (_ email );}}}

We can see that the ieventaggregator type parameter is passed in the constructor. If prism is used to build the Silverlight program, the ieventaggregator instance will be added to the container in the default bootstrapper, so we don't need to do more work. If you are not familiar with prism or bootstrapper, refer to these two articles (PRISM introduction, bootstrapper ).

The following code subscribes to the enewemail event:

Public class mailbox {public mailbox (ieventaggregator eventaggregator) {eventaggregator. getevent <incluenewemailevent> (). subscribe (onreceivednewemail);} // This method must be public void onreceivednewemail (mailviewmodel mail) {// do something }}

In this way, the released events can be immediately received, and the two components are only dependent on events and are loosely coupled with each other.

You can subscribe to, UNSUBSCRIBE, or even selectively accept certain events. The following uses a simulated simple mailbox client to demonstrate the use of event agregation.

The left side is the mail list, and a timer will receive an email every two seconds. Then, the mailbox client will update the mail list and click the list on the left to display the mail content on the right. If you click 'add this sender to blacklist', emails from this sender will no longer be accepted. If you click "Disconnect", the email will be stopped and you will continue to receive the email again. This is basically the requirement.

First, enable a timer when starting the program. An email will be received every two seconds and a new email will be sent to the Event Notification:

public class EmailReceiver{    public void Run()    {        var timer = new DispatcherTimer();        timer.Tick += (s, e) => EventAggregatorRepository.EventAggregator                                    .GetEvent<ReceiveNewEmailEvent>()                                    .Publish(EmailRepository.GetMail());        timer.Interval = new TimeSpan(0, 0, 0, 2);        timer.Start();    }}

The maillist component subscribes to this event and updates the mail list:

Public partial class maillist: usercontrol {private readonly observablecollection <mailviewmodel> _ mails = new observablecollection <mailviewmodel> (); // blacklist list private readonly list <string> _ refusedsenders = new list <string> (); Public maillist () {initializecomponent (); mailitems. itemssource = _ mails; subscribereceiveemailevent ();} private void subscribereceiveemailevent () {// The subscribe Method for subscribing to events provides several Methods, in addition to the simplest direct subscription, // You can also specify the thread type (for example, if you directly use system. threading. if timer is used, // threadoption must be used. uithread, otherwise an error will be reported), and whether or not the subscriber's reference is held, // or specify a filter to filter events. // In this example, the filter is used to reject the eventaggregatorrepository message from the sender included in the blacklist. eventaggregator. getevent <incluenewemailevent> (). subscribe (onreceivenewemail, threadoption. uithread, true, (Mail) =>! _ Refusedsenders. Contains (mail. From);} public void onreceivenewemail (mailviewmodel mail) {_ mails. insert (0, mail );}}

When you click the mail list on the left, the message is displayed in the mailcontent component on the right. This process is also completed by event aggregation.

// Icationicationobject is the base class of viewmodel supported by mvvm provided by Prism. // You can simplify the implementation of inotifypropertychanged interface. Public class mailviewmodel: icationicationobject {public mailviewmodel () {// delegatecommand is also a command type provided by Prism. viewmailcommand = new delegatecommand (onviewmail);} public icommand viewmailcommand {Get; private set;} public void onviewmail () {This. hasread = true; eventaggregatorrepository. eventaggregator. getevent <viewemailevent> (). publish (this );}}

When you click, the corresponding command logic is displayed, while mailcontent subscribes to viewemailevent and displays the passed mailviewmodel:

public partial class MailContent : UserControl{    public MailContent()    {        InitializeComponent();        EventAggregatorRepository.EventAggregator            .GetEvent<ViewEmailEvent>()            .Subscribe(OnViewEmail);    }    public void OnViewEmail(MailViewModel mail)    {        this.DataContext = mail;    }}

When you click Add the sender to the blacklist, addrefusesenderevent is published, and the maillist component that receives the event updates the blacklist, in this way, the filter filters out the emails of the senders that already exist in the blacklist:

public void OnRefusedSendersAdded(string sender){    if (!_refusedSenders.Contains(sender))    {        _refusedSenders.Add(sender);    }}

If you click disconnect or reconnect, A connectordisconnectmailserverevent event will be published. The prism event base class does not support events without parameters, that is, there is no way to create an event without parameters. So here we use the object type as the parameter type, and directly pass a null when passing the parameter.

EventAggregatorRepository.EventAggregator    .GetEvent<ConnectOrDisconnectMailServerEvent>()    .Publish(null);

When a maillist receives the event, it first determines whether the events have been subscribed to by enewemailevent. If the event is subscribed to, it will Unsubscribe. If the event is not subscribed to, it will subscribe again. To enable or disable email receiving:

Public partial class maillist: usercontrol {private readonly observablecollection <mailviewmodel> _ mails = new observablecollection <mailviewmodel> (); private readonly list <string> _ refusedsenders = new list <string> (); Public maillist () {initializecomponent (); subscribereceiveemailevent (); eventaggregatorrepository. eventaggregator. getevent <connectordisconnectmailserverevent> (). subscribe (onconnect Ordisconnectmailserver);} public void onconnectordisconnectmailserver (Object OBJ) {// determine whether the event bool hassubscribed = eventaggregatorrepository has been subscribed. eventaggregator. getevent <incluenewemailevent> (). contains (onreceivenewemail); If (hassubscribed) {publish ();} else {subscribereceiveemailevent () ;}} private void subscribereceiveemailevent () {eventaggregatorrepository. eventa Ggregator. getevent <incluenewemailevent> (). subscribe (onreceivenewemail, threadoption. uithread, true, (Mail) =>! _ Refusedsenders. contains (mail. from);} private void unsubscribereceiveemailevent () {// unsubscribe event eventaggregatorrepository. eventaggregator. getevent <incluenewemailevent> (). unsubscribe (onreceivenewemail);} public void onreceivenewemail (mailviewmodel mail) {_ mails. insert (0, mail );}}

Eventaggregation does not need to be built on the prism assembly program. For ease of operation, prism is not used to manage the program, and containers are not used. So I used a static global variable to save an ieventaggregator instance.

In this article, event aggregation is widely used for demonstration. We hope that you can use event aggregation carefully in your work. Although it is flexible to use, if there are too many events, it also makes people feel helpless and increases the difficulty of maintenance.

The sample code can be downloaded here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.