Monday, August 30, 2010

How To : Communicate between two user-controls using Event Aggregator

I found many posts in the asp.net, silverlight.net fourms regarding communication between user-controls, so i thought to blog a bit about communication between user-controls using Event Aggregator in silverlight which i found is the best way to communicate.

The main advantage for using an event aggregator to communicate between user-controls is, it removes the tight coupling between a publisher and a subscriber, by which a publisher/subscriber can evolve independently. Pre-requisites for understanding this blog post is to have a bit understanding of Event Aggregator.

Live Demo : Event Aggregator Sample
Source Code: At the end of this post :).

In this post i will explain how two user-controls can pass messages between them using event aggregator, consider a simple chat scenario where one user types-in some message and sends to to another user and vice-versa. My Visual Studio Solution looks as shown below, things to observe are
  • Microsoft Practices Composite dll's which are required for implementing the event aggregation
  • EventAggregator.cs which implements the interface IEventAggregator. (Note: will share the enitre source code at the end of this blog post :) )
  • "Kranthi.xaml" and "Kiran.xaml", two user controls which communicate using event aggregator.













Both the user controls have same functionality to implement. Lets see how the "Kranthi.xaml" user-control UI is likely to be, it contains following:
  • Text Box, where user enters message to publish.
  • Button, used to publish the entered message in TextBox.
  • ListBox, to display the received messages from the subscribed event.
"Kiran.xaml" user-control also has the same controls, so now i am ready with a sample user-interface which looks like below










So now i am defining two events to communicate
  1. MessageToKiran event is published by "Kranthi.xaml" and is subscribed by "Kiran.xaml".
  2. MessageToKranthi event is published by "Kiran.xaml" and is subscribed by "Kranthi.xaml".
Whenever an event is published, all the subscribers for that event get notified regarding the published message.
namespace EventAggregationSample
{
    public class MessageToKranthi : PresentationEvent<string> { }

    public class MessageToKiran : PresentationEvent<string> { }
}
Subscribing to Event:
Before subscribing or publishing a message, we need to instantiate EventAggregator and Subscribe to event as shown below
IEventAggregator Aggregator { get; set; }

//Constructor
public Kranthi()
{
    InitializeComponent();
    Aggregator = new EventAggregator();
    Aggregator.Subscribe<MessageToKranthi, string>(OnMessageToKiran);
}

public void OnMessageToKiran(PresentationEvent<string> e)
{
    ListBoxItem item = new ListBoxItem();
    item.Content = e.Payload;
    lbMessages.Items.Add(item);
}
In the Constructor, I've initialized the Aggregator and subscribed to the event MessageToKranthi, which has a payload of type string(which is our message). Whenever any user-control publishes MessageToKranthi event then "OnMessageToKiran" code gets executed.

Publishing an Event:
We can use event aggregator to send message for all subscribers of that event as below
Aggregator.SendMessage<MessageToKiran, string>(
    new MessageToKiran { Payload = tbMessage.Text }
    );
The above code publishes "MessageToKiran" event with the payload of the user entered text, this text is passed as payload to all the subscribers for this event.

To Complete the Communication, two user-controls should perform the following activities
  • Kranthi.xaml - Publish the event "MessageToKiran" and Subscribe for the event "MessageToKranthi"
  • Kiran.xaml - Publish the event "MessageToKranthi" and Subscribe for the event "MessageToKiran"
Finally here is the link for the source code which demonstrates the event aggregation sample. hope this helps someone.. :)

6 comments:

  1. its working now, perhaps googles fault. sorry

    please delete my comments

    thank you 4 the code. i hope (wish) its solve my problem

    ReplyDelete
  2. Hi, very nice post!!
    Is it possible to share the source code? The above link doesn't work. Thanks.

    ReplyDelete
  3. Hi Lorenzo, I've tried downloading using the link provided at the end of the post and succeded. The above link works for downloading the sample. On clicking of that link you will be redirected to the google docs where you can find teh link for downloading the source code..
    If you still find issue to get the source code, send me your email id, i will emaill the source code to that email.

    ReplyDelete
  4. Thank you for your prompt reply.
    Now the link works! Thank you again for sharing your code :)

    ReplyDelete
  5. Hi Kranthi,

    I just wanted to note that the event aggregator is usually a good choice when you have many objects that could potentially be the source of a certain type of event. (For example, several modules that want to notify that they have initialized or shut down.) This allows for a single object to receive events from multiple sources without registering an event handler with all of them.

    In very simple cases or when I want to have multiple objects listening for a single event source, I find it easier to just register an interface with instace of object in a container such as Unity and then have each module that needs to receive the event (perhaps such as user Login or Logoff) acquire the interface from the container and register with the event.

    Cheers!

    ReplyDelete
  6. Hi Joe,
    I haven't checked out unity container till now, thanks for mentioning that and posting a comment, will check out that soon.

    ReplyDelete