Components in a composite application often need to communicate with other components and services in the application in a loosely coupled way. To support this, Prism provides the EventAggregator component that implements a pub-sub event mechanism, thereby allowing components to publish events and other components to subscribe to those events without either of them requiring a reference to the other. The EventAggregator is often used to allow components defined in different modules to communicate with each other.

PubSubEvent
Connecting publishers and subscribers is done by the PubSubEvent class. This is the only implementation of the EventBase class that is included in the Prism Library. This class maintains the list of subscribers and handles event dispatching to the subscribers.
Event Publishing
Publishers raise an event by retrieving the event from the EventAggregator and calling the Publish method. To access the EventAggregator, you can use dependency injection by adding a parameter of type IEventAggregator to the class constructor.
That is shown in the following code.
- public Person SelectedPerson
- {
- get
- {
- return this.selectedPerson;
- }
- set
- {
- if(this.selectedPerson!=value)
- {
- this.selectedPerson = value;
- this.NotifyPropertyChanged("SelectedPerson");
- // Publish event.
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Publish(this.SelectedPerson);
- }
- }
- }
Event Subscribing
Subscribers can enlist with an event using one of the Subscribe method overloads available on the PubSubEvent class.
That is shown in the following code.
- SubscriptionToken subscriptionToken =
- this .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Subscribe((details) =>
- { this.Person = details;
- });
Note: Here we need to use both the publisher and subscriber types as the same.
Event Unsubscribing
If your subscriber no longer wants to receive events, you can unsubscribe using your subscriber's handler or you can unsubscribe using a subscription token.
That is shown in the following code.
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Unsubscribe(subscriptionToken);
Sample Code
Folder Structure: See the screen below.

In view
Provide the following code for Person1.xaml.
- <UserControl x:Class="PrismEventAggregator.Views.Person1"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- BorderBrush="Black"
- BorderThickness="2"
- d:DesignHeight="300"
- d:DesignWidth="300"
- mc:Ignorable="d">
- <Grid Margin="10 10 0 0">
- <DataGrid AutoGenerateColumns="False"
- CanUserAddRows="False"
- ItemsSource="{Binding PersonDetails}"
- SelectedItem="{Binding SelectedPerson}">
- <DataGrid.Columns>
- <DataGridTemplateColumn Header="Id">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Id}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTemplateColumn Header="Name">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Name}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTemplateColumn Header="Address">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Address}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- </DataGrid.Columns>
- </DataGrid>
- </Grid>
- </UserControl>
- /// <summary>
- /// Interaction logic for Person1.xaml
- /// </summary>
- public partial class Person1 : UserControl
- {
- public Person1()
- {
- InitializeComponent();
- this.DataContext = new Person1ViewModel(Event.EventInstance.EventAggregator);
- }
- }
- <UserControl x:Class="PrismEventAggregator.Views.Person2"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- BorderBrush="Black"
- BorderThickness="2"
- d:DesignHeight="300"
- d:DesignWidth="300"
- mc:Ignorable="d">
- <Grid Margin="10 10 0 0">
- <DataGrid AutoGenerateColumns="False"
- CanUserAddRows="False"
- ItemsSource="{Binding PersonDetails}"
- SelectedItem="{Binding SelectedPerson}">
- <DataGrid.Columns>
- <DataGridTemplateColumn Header="Id">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Id}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTemplateColumn Header="Name">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Name}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTemplateColumn Header="Address">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Address}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- </DataGrid.Columns>
- </DataGrid>
- </Grid>
- </UserControl>
- /// <summary>
- /// Interaction logic for Person2.xaml
- /// </summary>
- public partial class Person2 : UserControl
- {
- public Person2()
- {
- InitializeComponent();
- this.DataContext = new Person2ViewModel(Event.EventInstance.EventAggregator);
- }
- }
- <UserControl x:Class="PrismEventAggregator.Views.PersonDetails1"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Width="200"
- Height="250"
- BorderBrush="Black"
- BorderThickness="2">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="25" />
- <RowDefinition Height="*" />
- </Grid.RowDefinitions>
- <Button Width="80"
- Height="25"
- Margin="10,0,106,0"
- Command="{Binding Subscribe}"
- Content="Subscribe" />
- <Button Width="80"
- Height="25"
- Margin="106,0,10,0"
- Command="{Binding Unsubscribe}"
- Content="Unsubscribe" />
- <ContentControl Grid.Row="1" Content="{Binding Person}">
- <ContentControl.ContentTemplate>
- <DataTemplate>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="*" />
- </Grid.RowDefinitions>
- <TextBlock Grid.Row="0"
- Grid.RowSpan="2"
- Text="Person Details" />
- <TextBlock Grid.Row="2" Text="Id: " />
- <TextBlock Grid.Row="3" Text="{Binding Id}" />
- <TextBlock Grid.Row="4" Text="Name: " />
- <TextBlock Grid.Row="5" Text="{Binding Name}" />
- <TextBlock Grid.Row="6" Text="Address: " />
- <TextBlock Grid.Row="7" Text="{Binding Address}" />
- <TextBlock Grid.Row="8" Text="Photo" />
- <Image Grid.Row="8" Source="{Binding Photo}" />
- </Grid>
- </DataTemplate>
- </ContentControl.ContentTemplate>
- </ContentControl>
- </Grid>
- </UserControl>
- /// <summary>
- /// Interaction logic for PersonDetails1.xaml
- /// </summary>
- public partial class PersonDetails1 : UserControl
- {
- public PersonDetails1()
- {
- InitializeComponent();
- this.DataContext = new PersonDetails1ViewModel(Event.EventInstance.EventAggregator);
- }
- }
- <UserControl x:Class="PrismEventAggregator.Views.PersonDetails2"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Width="200"
- Height="250"
- BorderBrush="Black"
- BorderThickness="2">
- <Grid Margin="10">
- <ContentControl Content="{Binding Person}">
- <ContentControl.ContentTemplate>
- <DataTemplate>
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="auto" />
- <RowDefinition Height="*" />
- </Grid.RowDefinitions>
- <TextBlock Grid.Row="0"
- Grid.RowSpan="2"
- Text="Person Details" />
- <TextBlock Grid.Row="2" Text="Id: " />
- <TextBlock Grid.Row="3" Text="{Binding Id}" />
- <TextBlock Grid.Row="4" Text="Name: " />
- <TextBlock Grid.Row="5" Text="{Binding Name}" />
- <TextBlock Grid.Row="6" Text="Address: " />
- <TextBlock Grid.Row="7" Text="{Binding Address}" />
- <TextBlock Grid.Row="8" Text="Photo" />
- <Image Grid.Row="8" Source="{Binding Photo}" />
- </Grid>
- </DataTemplate>
- </ContentControl.ContentTemplate>
- </ContentControl>
- </Grid>
- </UserControl>
- /// <summary>
- /// Interaction logic for PersonDetails2.xaml
- /// </summary>
- public partial class PersonDetails2 : UserControl
- {
- public PersonDetails2()
- {
- InitializeComponent();
- this.DataContext = new PersonDetails2ViewModel(Event.EventInstance.EventAggregator);
- }
- }
Provide the following code for Person1ViewModel.cs.
Provide the following code for Person2ViewModel.cs.
Provide the following code for PersonDetails1ViewModel.cs.
- public class Person1ViewModel : INotifyPropertyChanged
- {
- #region Instance Properties
- public List<Person> PersonDetails
- {
- get
- {
- return this.personDetails;
- }
- set
- {
- if(this.personDetails != value)
- {
- this.personDetails = value;
- this.NotifyPropertyChanged("PersonDetails");
- }
- }
- }
- public Person SelectedPerson {
- get
- {
- return this.selectedPerson;
- }
- set
- {
- if(this.selectedPerson!=value)
- {
- this.selectedPerson = value;
- this.NotifyPropertyChanged("SelectedPerson");
- // Publish event.
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Publish(this.SelectedPerson);
- }
- }
- }
- #endregion
- #region Constructors
- public Person1ViewModel(IEventAggregator iEventAggregator)
- {
- this.iEventAggregator = iEventAggregator;
- this.PersonDetails = new List<Person>();
- this.PersonDetails.Add(new Person() { Address = "Hyderabad", Name = "Hari", Id = 1, Photo = "/PrismEventAggregator;component/Resources/Images/img_chania.jpg" });
- this.PersonDetails.Add(new Person() { Address = "Guntur", Name = "Murali", Id = 2, Photo = "/PrismEventAggregator;component/Resources/Images/img_chania2.jpg" });
- this.PersonDetails.Add(new Person() { Address = "Ongole", Name = "Varun", Id = 3, Photo = "/PrismEventAggregator;component/Resources/Images/img_flower2.jpg" });
- }
- #endregion
- #region INotifyPropertyChanged Implementation
- public event PropertyChangedEventHandler PropertyChanged;
- protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- #endregion
- #region Instance Fields
- private List<Person> personDetails;
- private Person selectedPerson;
- private IEventAggregator iEventAggregator;
- #endregion
- }
- public class Person2ViewModel : INotifyPropertyChanged
- {
- #region Instance Properties
- public List<Person> PersonDetails
- {
- get
- {
- return this.personDetails;
- }
- set
- {
- if (this.personDetails != value)
- {
- this.personDetails = value;
- this.NotifyPropertyChanged("PersonDetails");
- }
- }
- }
- public Person SelectedPerson
- {
- get
- {
- return this.selectedPerson;
- }
- set
- {
- if (this.selectedPerson != value)
- {
- this.selectedPerson = value;
- this.NotifyPropertyChanged("SelectedPerson");
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Publish(this.SelectedPerson);
- }
- }
- }
- #endregion
- #region Constructors
- public Person2ViewModel(IEventAggregator iEventAggregator)
- {
- this.iEventAggregator = iEventAggregator;
- this.PersonDetails = new List<Person>();
- this.PersonDetails.Add(new Person() { Address = "Vizag", Name = "Pavan", Id = 1, Photo = "/PrismEventAggregator;component/Resources/Images/img1.jpg" });
- this.PersonDetails.Add(new Person() { Address = "Vijayawada", Name = "Mahesh", Id = 2, Photo = "/PrismEventAggregator;component/Resources/Images/img2.jpg" });
- this.PersonDetails.Add(new Person() { Address = "Nellore", Name = "Srinivas", Id = 3, Photo = "/PrismEventAggregator;component/Resources/Images/img3.jpg" });
- }
- #endregion
- #region INotifyPropertyChanged Implementation
- public event PropertyChangedEventHandler PropertyChanged;
- protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- #endregion
- #region Instance Fields
- private List<Person> personDetails;
- private Person selectedPerson;
- private IEventAggregator iEventAggregator;
- #endregion
- }
- public class PersonDetails1ViewModel: INotifyPropertyChanged
- {
- #region Instance Properties
- public Person Person {
- get
- {
- return this.persionDetails;
- }
- set
- {
- if(this.persionDetails!=value)
- {
- this.persionDetails = value;
- this.NotifyPropertyChanged("Person");
- }
- }
- }
- public ICommand Unsubscribe { get; set; }
- public ICommand Subscribe { get; set; }
- #endregion
- #region Constructors
- public PersonDetails1ViewModel(IEventAggregator iEventAggregator)
- {
- this.iEventAggregator = iEventAggregator;
- SubscriptionToken subscriptionToken =
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Subscribe((details) =>
- {
- this.Person = details;
- });
- this.Subscribe = new DelegateCommand(
- () =>
- {
- subscriptionToken =
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Subscribe((details) =>
- {
- this.Person = details;
- });
- });
- this.Unsubscribe = new DelegateCommand(
- () => {
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Unsubscribe(subscriptionToken);
- });
- }
- #endregion
- #region INotifyPropertyChanged Implementation
- public event PropertyChangedEventHandler PropertyChanged;
- protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- #endregion
- #region Instance Fields
- private Person persionDetails;
- private IEventAggregator iEventAggregator;
- #endregion
- }
- public class PersonDetails2ViewModel : INotifyPropertyChanged
- {
- #region Instance Properties
- public Person Person
- {
- get
- {
- return this.persionDetails;
- }
- set
- {
- if (this.persionDetails != value)
- {
- this.persionDetails = value;
- this.NotifyPropertyChanged("Person");
- }
- }
- }
- #endregion
- #region Constructors
- public PersonDetails2ViewModel(IEventAggregator iEventAggregator)
- {
- this.iEventAggregator = iEventAggregator;
- this
- .iEventAggregator
- .GetEvent<PubSubEvent<Person>>()
- .Subscribe((details) =>
- {
- this.Person = details;
- });
- }
- #endregion
- #region INotifyPropertyChanged Implementation
- public event PropertyChangedEventHandler PropertyChanged;
- protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- #endregion
- #region Instance Fields
- private Person persionDetails;
- private IEventAggregator iEventAggregator;
- #endregion
- }
Provide the following code for Event.cs.
- public sealed class Event
- {
- #region Class Properties
- internal static Event EventInstance
- {
- get
- {
- return eventInstance;
- }
- }
- #endregion
- #region Instance Properties
- internal IEventAggregator EventAggregator
- {
- get
- {
- if (eventAggregator == null)
- {
- eventAggregator = new EventAggregator();
- }
- return eventAggregator;
- }
- }
- #endregion
- #region Constructors
- private Event()
- {
- }
- #endregion
- #region Class Fields
- private static readonly Event eventInstance = new Event();
- #endregion
- #region Instance Fields
- private IEventAggregator eventAggregator;
- #endregion
- }
- Provide the following code for Person.cs.
- public class Person
- {
- #region Instance Properties
- public int Id { get; set; }
- public string Name { get; set; }
- public string Photo { get; set; }
- public string Address { get; set; }
- #endregion
- }

Karthik Muthu KaruppanPosted Apr 23, 2015, 11:36 AM
nice
Sibeesh VenuPosted Apr 20, 2015, 6:37 AM
good one.
Mahesh ChandPosted Apr 17, 2015, 7:41 AM
Nice Vinod and welcome to C# Corner. I think article belongs to WPF? You can edit it and move it to WPF. Same with your other article that is published in C# category. You may also want to fix the code formatting by removing extra spacing. Thank you for being a part of the community. Cheers!
NitinPosted Apr 17, 2015, 6:35 AM
nice
Santhakumar MunuswamyPosted Apr 17, 2015, 12:05 AM
good