EventAggregator
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);
- }
- }
- }
Here I have taken the property “SelectedPerson” and with the property setter I have published an event.
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;
- });
Here I have taken the property “Person” and initialized the published event parameter to person.
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);
Here I have unsubscribed using the subscriber's
“subscriptionToken”.
Sample CodeFolder Structure: See the screen below.
In viewProvide 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>
Provide the following code for Person1.xaml.cs.
- /// <summary>
- /// Interaction logic for Person1.xaml
- /// </summary>
- public partial class Person1 : UserControl
- {
- public Person1()
- {
- InitializeComponent();
- this.DataContext = new Person1ViewModel(Event.EventInstance.EventAggregator);
- }
- }
Provide the following code for Person2.xaml.
- <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>
Provide the following code for Person2.xaml.cs.
- /// <summary>
- /// Interaction logic for Person2.xaml
- /// </summary>
- public partial class Person2 : UserControl
- {
- public Person2()
- {
- InitializeComponent();
- this.DataContext = new Person2ViewModel(Event.EventInstance.EventAggregator);
- }
- }
Provide the following code for PersonDetails1.xaml.
- <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>
Provide the following code for PersonDetails1.xaml.cs.
- /// <summary>
- /// Interaction logic for PersonDetails1.xaml
- /// </summary>
- public partial class PersonDetails1 : UserControl
- {
- public PersonDetails1()
- {
- InitializeComponent();
- this.DataContext = new PersonDetails1ViewModel(Event.EventInstance.EventAggregator);
- }
- }
Provide the following code for PersonDetails2.xaml.
- <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>
Provide the following code for PersonDetails2.xaml.cs.
- /// <summary>
- /// Interaction logic for PersonDetails2.xaml
- /// </summary>
- public partial class PersonDetails2 : UserControl
- {
- public PersonDetails2()
- {
- InitializeComponent();
- this.DataContext = new PersonDetails2ViewModel(Event.EventInstance.EventAggregator);
- }
- }
In ViewModel
Provide the following code for Person1ViewModel.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
-
- }
Provide the following code for Person2ViewModel.cs.
- 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
-
- }
Provide the following code for PersonDetails1ViewModel.cs.
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
-
- }
See the Final Screen Shot