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.
  1. public Person SelectedPerson
  2. {
  3. get
  4. {
  5. return this.selectedPerson;
  6. }
  7. set
  8. {
  9. if(this.selectedPerson!=value)
  10. {
  11. this.selectedPerson = value;
  12. this.NotifyPropertyChanged("SelectedPerson");
  13. // Publish event.
  14. this
  15. .iEventAggregator
  16. .GetEvent<PubSubEvent<Person>>()
  17. .Publish(this.SelectedPerson);
  18. }
  19. }
  20. }
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.
  1. SubscriptionToken subscriptionToken =
  2. this .iEventAggregator
  3. .GetEvent<PubSubEvent<Person>>()
  4. .Subscribe((details) =>
  5. { this.Person = details;
  6. });
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.
  1. this
  2. .iEventAggregator
  3. .GetEvent<PubSubEvent<Person>>()
  4. .Unsubscribe(subscriptionToken);
Here I have unsubscribed using the subscriber's “subscriptionToken”.

Sample Code

Folder Structure: See the screen below.



In view

Provide the following code for Person1.xaml.
  1. <UserControl x:Class="PrismEventAggregator.Views.Person1"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. BorderBrush="Black"
  7. BorderThickness="2"
  8. d:DesignHeight="300"
  9. d:DesignWidth="300"
  10. mc:Ignorable="d">
  11. <Grid Margin="10 10 0 0">
  12. <DataGrid AutoGenerateColumns="False"
  13. CanUserAddRows="False"
  14. ItemsSource="{Binding PersonDetails}"
  15. SelectedItem="{Binding SelectedPerson}">
  16. <DataGrid.Columns>
  17. <DataGridTemplateColumn Header="Id">
  18. <DataGridTemplateColumn.CellTemplate>
  19. <DataTemplate>
  20. <TextBlock Text="{Binding Id}" />
  21. </DataTemplate>
  22. </DataGridTemplateColumn.CellTemplate>
  23. </DataGridTemplateColumn>
  24. <DataGridTemplateColumn Header="Name">
  25. <DataGridTemplateColumn.CellTemplate>
  26. <DataTemplate>
  27. <TextBlock Text="{Binding Name}" />
  28. </DataTemplate>
  29. </DataGridTemplateColumn.CellTemplate>
  30. </DataGridTemplateColumn>
  31. <DataGridTemplateColumn Header="Address">
  32. <DataGridTemplateColumn.CellTemplate>
  33. <DataTemplate>
  34. <TextBlock Text="{Binding Address}" />
  35. </DataTemplate>
  36. </DataGridTemplateColumn.CellTemplate>
  37. </DataGridTemplateColumn>
  38. </DataGrid.Columns>
  39. </DataGrid>
  40. </Grid>
  41. </UserControl>
Provide the following code for Person1.xaml.cs.
  1. /// <summary>
  2. /// Interaction logic for Person1.xaml
  3. /// </summary>
  4. public partial class Person1 : UserControl
  5. {
  6. public Person1()
  7. {
  8. InitializeComponent();
  9. this.DataContext = new Person1ViewModel(Event.EventInstance.EventAggregator);
  10. }
  11. }
Provide the following code for Person2.xaml.
  1. <UserControl x:Class="PrismEventAggregator.Views.Person2"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. BorderBrush="Black"
  7. BorderThickness="2"
  8. d:DesignHeight="300"
  9. d:DesignWidth="300"
  10. mc:Ignorable="d">
  11. <Grid Margin="10 10 0 0">
  12. <DataGrid AutoGenerateColumns="False"
  13. CanUserAddRows="False"
  14. ItemsSource="{Binding PersonDetails}"
  15. SelectedItem="{Binding SelectedPerson}">
  16. <DataGrid.Columns>
  17. <DataGridTemplateColumn Header="Id">
  18. <DataGridTemplateColumn.CellTemplate>
  19. <DataTemplate>
  20. <TextBlock Text="{Binding Id}" />
  21. </DataTemplate>
  22. </DataGridTemplateColumn.CellTemplate>
  23. </DataGridTemplateColumn>
  24. <DataGridTemplateColumn Header="Name">
  25. <DataGridTemplateColumn.CellTemplate>
  26. <DataTemplate>
  27. <TextBlock Text="{Binding Name}" />
  28. </DataTemplate>
  29. </DataGridTemplateColumn.CellTemplate>
  30. </DataGridTemplateColumn>
  31. <DataGridTemplateColumn Header="Address">
  32. <DataGridTemplateColumn.CellTemplate>
  33. <DataTemplate>
  34. <TextBlock Text="{Binding Address}" />
  35. </DataTemplate>
  36. </DataGridTemplateColumn.CellTemplate>
  37. </DataGridTemplateColumn>
  38. </DataGrid.Columns>
  39. </DataGrid>
  40. </Grid>
  41. </UserControl>
Provide the following code for Person2.xaml.cs.
  1. /// <summary>
  2. /// Interaction logic for Person2.xaml
  3. /// </summary>
  4. public partial class Person2 : UserControl
  5. {
  6. public Person2()
  7. {
  8. InitializeComponent();
  9. this.DataContext = new Person2ViewModel(Event.EventInstance.EventAggregator);
  10. }
  11. }
Provide the following code for PersonDetails1.xaml.
  1. <UserControl x:Class="PrismEventAggregator.Views.PersonDetails1"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Width="200"
  5. Height="250"
  6. BorderBrush="Black"
  7. BorderThickness="2">
  8. <Grid>
  9. <Grid.RowDefinitions>
  10. <RowDefinition Height="25" />
  11. <RowDefinition Height="*" />
  12. </Grid.RowDefinitions>
  13. <Button Width="80"
  14. Height="25"
  15. Margin="10,0,106,0"
  16. Command="{Binding Subscribe}"
  17. Content="Subscribe" />
  18. <Button Width="80"
  19. Height="25"
  20. Margin="106,0,10,0"
  21. Command="{Binding Unsubscribe}"
  22. Content="Unsubscribe" />
  23. <ContentControl Grid.Row="1" Content="{Binding Person}">
  24. <ContentControl.ContentTemplate>
  25. <DataTemplate>
  26. <Grid>
  27. <Grid.RowDefinitions>
  28. <RowDefinition Height="auto" />
  29. <RowDefinition Height="auto" />
  30. <RowDefinition Height="auto" />
  31. <RowDefinition Height="auto" />
  32. <RowDefinition Height="auto" />
  33. <RowDefinition Height="auto" />
  34. <RowDefinition Height="auto" />
  35. <RowDefinition Height="auto" />
  36. <RowDefinition Height="auto" />
  37. <RowDefinition Height="auto" />
  38. <RowDefinition Height="*" />
  39. </Grid.RowDefinitions>
  40. <TextBlock Grid.Row="0"
  41. Grid.RowSpan="2"
  42. Text="Person Details" />
  43. <TextBlock Grid.Row="2" Text="Id: " />
  44. <TextBlock Grid.Row="3" Text="{Binding Id}" />
  45. <TextBlock Grid.Row="4" Text="Name: " />
  46. <TextBlock Grid.Row="5" Text="{Binding Name}" />
  47. <TextBlock Grid.Row="6" Text="Address: " />
  48. <TextBlock Grid.Row="7" Text="{Binding Address}" />
  49. <TextBlock Grid.Row="8" Text="Photo" />
  50. <Image Grid.Row="8" Source="{Binding Photo}" />
  51. </Grid>
  52. </DataTemplate>
  53. </ContentControl.ContentTemplate>
  54. </ContentControl>
  55. </Grid>
  56. </UserControl>
Provide the following code for PersonDetails1.xaml.cs.
  1. /// <summary>
  2. /// Interaction logic for PersonDetails1.xaml
  3. /// </summary>
  4. public partial class PersonDetails1 : UserControl
  5. {
  6. public PersonDetails1()
  7. {
  8. InitializeComponent();
  9. this.DataContext = new PersonDetails1ViewModel(Event.EventInstance.EventAggregator);
  10. }
  11. }
Provide the following code for PersonDetails2.xaml.
  1. <UserControl x:Class="PrismEventAggregator.Views.PersonDetails2"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Width="200"
  5. Height="250"
  6. BorderBrush="Black"
  7. BorderThickness="2">
  8. <Grid Margin="10">
  9. <ContentControl Content="{Binding Person}">
  10. <ContentControl.ContentTemplate>
  11. <DataTemplate>
  12. <Grid>
  13. <Grid.RowDefinitions>
  14. <RowDefinition Height="auto" />
  15. <RowDefinition Height="auto" />
  16. <RowDefinition Height="auto" />
  17. <RowDefinition Height="auto" />
  18. <RowDefinition Height="auto" />
  19. <RowDefinition Height="auto" />
  20. <RowDefinition Height="auto" />
  21. <RowDefinition Height="auto" />
  22. <RowDefinition Height="auto" />
  23. <RowDefinition Height="auto" />
  24. <RowDefinition Height="*" />
  25. </Grid.RowDefinitions>
  26. <TextBlock Grid.Row="0"
  27. Grid.RowSpan="2"
  28. Text="Person Details" />
  29. <TextBlock Grid.Row="2" Text="Id: " />
  30. <TextBlock Grid.Row="3" Text="{Binding Id}" />
  31. <TextBlock Grid.Row="4" Text="Name: " />
  32. <TextBlock Grid.Row="5" Text="{Binding Name}" />
  33. <TextBlock Grid.Row="6" Text="Address: " />
  34. <TextBlock Grid.Row="7" Text="{Binding Address}" />
  35. <TextBlock Grid.Row="8" Text="Photo" />
  36. <Image Grid.Row="8" Source="{Binding Photo}" />
  37. </Grid>
  38. </DataTemplate>
  39. </ContentControl.ContentTemplate>
  40. </ContentControl>
  41. </Grid>
  42. </UserControl>
Provide the following code for PersonDetails2.xaml.cs.
  1. /// <summary>
  2. /// Interaction logic for PersonDetails2.xaml
  3. /// </summary>
  4. public partial class PersonDetails2 : UserControl
  5. {
  6. public PersonDetails2()
  7. {
  8. InitializeComponent();
  9. this.DataContext = new PersonDetails2ViewModel(Event.EventInstance.EventAggregator);
  10. }
  11. }
In ViewModel

Provide the following code for Person1ViewModel.cs.
  1. public class Person1ViewModel : INotifyPropertyChanged
  2. {
  3. #region Instance Properties
  4. public List<Person> PersonDetails
  5. {
  6. get
  7. {
  8. return this.personDetails;
  9. }
  10. set
  11. {
  12. if(this.personDetails != value)
  13. {
  14. this.personDetails = value;
  15. this.NotifyPropertyChanged("PersonDetails");
  16. }
  17. }
  18. }
  19. public Person SelectedPerson {
  20. get
  21. {
  22. return this.selectedPerson;
  23. }
  24. set
  25. {
  26. if(this.selectedPerson!=value)
  27. {
  28. this.selectedPerson = value;
  29. this.NotifyPropertyChanged("SelectedPerson");
  30. // Publish event.
  31. this
  32. .iEventAggregator
  33. .GetEvent<PubSubEvent<Person>>()
  34. .Publish(this.SelectedPerson);
  35. }
  36. }
  37. }
  38. #endregion
  39. #region Constructors
  40. public Person1ViewModel(IEventAggregator iEventAggregator)
  41. {
  42. this.iEventAggregator = iEventAggregator;
  43. this.PersonDetails = new List<Person>();
  44. this.PersonDetails.Add(new Person() { Address = "Hyderabad", Name = "Hari", Id = 1, Photo = "/PrismEventAggregator;component/Resources/Images/img_chania.jpg" });
  45. this.PersonDetails.Add(new Person() { Address = "Guntur", Name = "Murali", Id = 2, Photo = "/PrismEventAggregator;component/Resources/Images/img_chania2.jpg" });
  46. this.PersonDetails.Add(new Person() { Address = "Ongole", Name = "Varun", Id = 3, Photo = "/PrismEventAggregator;component/Resources/Images/img_flower2.jpg" });
  47. }
  48. #endregion
  49. #region INotifyPropertyChanged Implementation
  50. public event PropertyChangedEventHandler PropertyChanged;
  51. protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
  52. {
  53. if (PropertyChanged != null)
  54. {
  55. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  56. }
  57. }
  58. #endregion
  59. #region Instance Fields
  60. private List<Person> personDetails;
  61. private Person selectedPerson;
  62. private IEventAggregator iEventAggregator;
  63. #endregion
  64. }
Provide the following code for Person2ViewModel.cs.
  1. public class Person2ViewModel : INotifyPropertyChanged
  2. {
  3. #region Instance Properties
  4. public List<Person> PersonDetails
  5. {
  6. get
  7. {
  8. return this.personDetails;
  9. }
  10. set
  11. {
  12. if (this.personDetails != value)
  13. {
  14. this.personDetails = value;
  15. this.NotifyPropertyChanged("PersonDetails");
  16. }
  17. }
  18. }
  19. public Person SelectedPerson
  20. {
  21. get
  22. {
  23. return this.selectedPerson;
  24. }
  25. set
  26. {
  27. if (this.selectedPerson != value)
  28. {
  29. this.selectedPerson = value;
  30. this.NotifyPropertyChanged("SelectedPerson");
  31. this
  32. .iEventAggregator
  33. .GetEvent<PubSubEvent<Person>>()
  34. .Publish(this.SelectedPerson);
  35. }
  36. }
  37. }
  38. #endregion
  39. #region Constructors
  40. public Person2ViewModel(IEventAggregator iEventAggregator)
  41. {
  42. this.iEventAggregator = iEventAggregator;
  43. this.PersonDetails = new List<Person>();
  44. this.PersonDetails.Add(new Person() { Address = "Vizag", Name = "Pavan", Id = 1, Photo = "/PrismEventAggregator;component/Resources/Images/img1.jpg" });
  45. this.PersonDetails.Add(new Person() { Address = "Vijayawada", Name = "Mahesh", Id = 2, Photo = "/PrismEventAggregator;component/Resources/Images/img2.jpg" });
  46. this.PersonDetails.Add(new Person() { Address = "Nellore", Name = "Srinivas", Id = 3, Photo = "/PrismEventAggregator;component/Resources/Images/img3.jpg" });
  47. }
  48. #endregion
  49. #region INotifyPropertyChanged Implementation
  50. public event PropertyChangedEventHandler PropertyChanged;
  51. protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
  52. {
  53. if (PropertyChanged != null)
  54. {
  55. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  56. }
  57. }
  58. #endregion
  59. #region Instance Fields
  60. private List<Person> personDetails;
  61. private Person selectedPerson;
  62. private IEventAggregator iEventAggregator;
  63. #endregion
  64. }
Provide the following code for PersonDetails1ViewModel.cs.
  1. public class PersonDetails1ViewModel: INotifyPropertyChanged
  2. {
  3. #region Instance Properties
  4. public Person Person {
  5. get
  6. {
  7. return this.persionDetails;
  8. }
  9. set
  10. {
  11. if(this.persionDetails!=value)
  12. {
  13. this.persionDetails = value;
  14. this.NotifyPropertyChanged("Person");
  15. }
  16. }
  17. }
  18. public ICommand Unsubscribe { get; set; }
  19. public ICommand Subscribe { get; set; }
  20. #endregion
  21. #region Constructors
  22. public PersonDetails1ViewModel(IEventAggregator iEventAggregator)
  23. {
  24. this.iEventAggregator = iEventAggregator;
  25. SubscriptionToken subscriptionToken =
  26. this
  27. .iEventAggregator
  28. .GetEvent<PubSubEvent<Person>>()
  29. .Subscribe((details) =>
  30. {
  31. this.Person = details;
  32. });
  33. this.Subscribe = new DelegateCommand(
  34. () =>
  35. {
  36. subscriptionToken =
  37. this
  38. .iEventAggregator
  39. .GetEvent<PubSubEvent<Person>>()
  40. .Subscribe((details) =>
  41. {
  42. this.Person = details;
  43. });
  44. });
  45. this.Unsubscribe = new DelegateCommand(
  46. () => {
  47. this
  48. .iEventAggregator
  49. .GetEvent<PubSubEvent<Person>>()
  50. .Unsubscribe(subscriptionToken);
  51. });
  52. }
  53. #endregion
  54. #region INotifyPropertyChanged Implementation
  55. public event PropertyChangedEventHandler PropertyChanged;
  56. protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
  57. {
  58. if (PropertyChanged != null)
  59. {
  60. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  61. }
  62. }
  63. #endregion
  64. #region Instance Fields
  65. private Person persionDetails;
  66. private IEventAggregator iEventAggregator;
  67. #endregion
  68. }
Provide the following code for PersonDetails2ViewModel.cs.
  1. public class PersonDetails2ViewModel : INotifyPropertyChanged
  2. {
  3. #region Instance Properties
  4. public Person Person
  5. {
  6. get
  7. {
  8. return this.persionDetails;
  9. }
  10. set
  11. {
  12. if (this.persionDetails != value)
  13. {
  14. this.persionDetails = value;
  15. this.NotifyPropertyChanged("Person");
  16. }
  17. }
  18. }
  19. #endregion
  20. #region Constructors
  21. public PersonDetails2ViewModel(IEventAggregator iEventAggregator)
  22. {
  23. this.iEventAggregator = iEventAggregator;
  24. this
  25. .iEventAggregator
  26. .GetEvent<PubSubEvent<Person>>()
  27. .Subscribe((details) =>
  28. {
  29. this.Person = details;
  30. });
  31. }
  32. #endregion
  33. #region INotifyPropertyChanged Implementation
  34. public event PropertyChangedEventHandler PropertyChanged;
  35. protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
  36. {
  37. if (PropertyChanged != null)
  38. {
  39. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  40. }
  41. }
  42. #endregion
  43. #region Instance Fields
  44. private Person persionDetails;
  45. private IEventAggregator iEventAggregator;
  46. #endregion
  47. }
In Model
Provide the following code for Event.cs.
  1. public sealed class Event
  2. {
  3. #region Class Properties
  4. internal static Event EventInstance
  5. {
  6. get
  7. {
  8. return eventInstance;
  9. }
  10. }
  11. #endregion
  12. #region Instance Properties
  13. internal IEventAggregator EventAggregator
  14. {
  15. get
  16. {
  17. if (eventAggregator == null)
  18. {
  19. eventAggregator = new EventAggregator();
  20. }
  21. return eventAggregator;
  22. }
  23. }
  24. #endregion
  25. #region Constructors
  26. private Event()
  27. {
  28. }
  29. #endregion
  30. #region Class Fields
  31. private static readonly Event eventInstance = new Event();
  32. #endregion
  33. #region Instance Fields
  34. private IEventAggregator eventAggregator;
  35. #endregion
  36. }
  37. Provide the following code for Person.cs.
  38. public class Person
  39. {
  40. #region Instance Properties
  41. public int Id { get; set; }
  42. public string Name { get; set; }
  43. public string Photo { get; set; }
  44. public string Address { get; set; }
  45. #endregion
  46. }
See the Final Screen Shot