In WPF MVVM we might want to send a message from one View Model to another. For example, if we want to close a window and return data to the opener window. To allow such data exchange we can use a messaging system.

For that we have the EventAggregator pattern.

The EventAggregator class will store all the instances that are being tracked. So when a message is published all those listed instances will be notified.

  1. public interface IListen { }
  2. public interface IListen<T> : IListen
  3. {
  4. void Handle(T obj);
  5. }
  6. public class EventAggregator
  7. {
  8. private List<IListen> subscribers = new List<IListen>();
  9. public void Subscribe(IListen model)
  10. {
  11. this.subscribers.Add(model);
  12. }
  13. public void Unsubscribe(IListen model)
  14. {
  15. this.subscribers.Remove(model);
  16. }
  17. public void Publish<T>(T message)
  18. {
  19. foreach (var item in this.subscribers.OfType<IListen<T>>())
  20. {
  21. item.Handle(message);
  22. }
  23. }
  24. }
To demonstrate this example let's use a class Car that will listen for signals and a class Guard that will notify the cars using a SignalMessage class.
  1. public class Car : IListen<SignalMessage>
  2. {
  3. public Car(EventAggregator eventAggregator)
  4. {
  5. eventAggregator.Subscribe(this);
  6. }
  7. public void Handle(SignalMessage obj)
  8. {
  9. Console.WriteLine("I'm a car and a guard is telling me to stop!");
  10. }
  11. }
  12. public class Guard
  13. {
  14. private EventAggregator eventAggregator;
  15. public Guard(EventAggregator eventAggregator)
  16. {
  17. this.eventAggregator = eventAggregator;
  18. }
  19. public void SignalCars()
  20. {
  21. this.eventAggregator.Publish(new SignalMessage { Message = "Stop" });
  22. }
  23. }
  24. public class SignalMessage
  25. {
  26. public string Message { get; set; }
  27. }
Run this application.
  1. static void Main(string[] args)
  2. {
  3. var eventAggregator = new EventAggregator();
  4. var car1 = new Car(eventAggregator);
  5. var car2 = new Car(eventAggregator);
  6. var car3 = new Car(eventAggregator);
  7. var guard = new Guard(eventAggregator);
  8. guard.SignalCars();
  9. Console.ReadKey(true);
  10. }
We will see that all the cards are being notified:

output