In previous two parts we saw two different implementations of mediator design pattern here and here. Although in second part we remove the dependencies of specific user control from the mediator class and make it flexible enough to register as many client as you want using Register method. But we actually introduced one dependency for all the client. Now all of our client has to implement IMediatorClient interface.
Let’s take one step further and try to remove that dependency too. We change our mediator class little bit and instead of registering the mediator client, now we are going to register the call back method of every client. Our register method accept Action<object> type that is actually a callback method. And in send method we call all the method using DynamicInvoke method of Delegate class to call the callback method. Here is updated version of our mediator class.
using System.Collections.Generic;
namespace MediatorUserControl
{
public class Mediator
{
private List<Action<object>> actions = new List<Action<object>>();
public Mediator()
{
}
public void Register( Action<object> action)
{
actions.Add(action);
}
public void Send(object message)
{
foreach (var action in actions)
{
action.DynamicInvoke(message);
}
}
}
}
Now we no more need to implement IMediatorClient interfaceSSSDFR55556 for our user controls. In our main window, we are registering the call back methods. Here is a piece of code to use the mediator.
Mediator.Register(studentform.Notify);
Mediator.Register(studentlist.Notify);
studentform.Mediator = Mediator;
studentlist.Mediator = Mediator;
Here is a complete code of our main window.
using System.Windows;
namespace MediatorUserControl
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<Student> students = new ObservableCollection<Student>();
public Mediator Mediator
{ get; set; }
public MainWindow()
{
InitializeComponent();
students.Add(new Student() { ID = "1", FirstName = "Bob", LastName = "Smith", Degree = "Associate" });
students.Add(new Student() { ID = "2", FirstName = "Alex", LastName = "White", Degree = "Certificate" });
students.Add(new Student() { ID = "3", FirstName = "Chris", LastName = "Martin", Degree = "Master" });
students.Add(new Student() { ID = "4", FirstName = "Michal", LastName = "Brown", Degree = "Bachlor" });
Mediator = new Mediator();
Mediator.Register(studentform.Notify);
Mediator.Register(studentlist.Notify);
studentform.Mediator = Mediator;
studentlist.Mediator = Mediator;
DataContext = students;
}
}
}
The code for both user controls are exactly same, the only difference is that now we are no more implementing the IMediatorClient interface and we even don’t need that interface in our project.
Here is a code for CustomizedList user control.
using System.Windows.Controls;
namespace MediatorUserControl
{
/// <summary>
/// Interaction logic for CustomizedList.xaml
/// </summary>
public partial class CustomizedList : UserControl
{
public static readonly DependencyProperty SelectedStudentProperty =
DependencyProperty.Register("SelectedStudent", typeof(Student), typeof(CustomizedList));
public Student SelectedStudent
{
get { return (Student)GetValue(SelectedStudentProperty); }
set { SetValue(SelectedStudentProperty, value); }
}
public Mediator Mediator
{ get; set; }
public CustomizedList()
{
InitializeComponent();
}
private void list_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedStudent = list.SelectedItem as Student;
Send(SelectedStudent);
}
public void Send(object message)
{
Mediator.Send(message);
}
public void Notify(object message)
{
}
}
}
And here is a code of user control of StudentForm user control.
namespace MediatorUserControl
{
/// <summary>
/// Interaction logic for StudentForm.xaml
/// </summary>
public partial class StudentForm : UserControl
{
public Mediator Mediator
{ get; set; }
public StudentForm()
{
InitializeComponent();
}
public void Send(object message)
{
}
public void Notify(object message)
{
Student student = message as Student;
if (student != null)
{
DataContext = student;
}
}
}
}
The output of this program is exactly same as previous program.

Really interesting, I will take a look later to implement this in one of my personal project.
Thank you for the second and third part of this article
Laurent
By: Laurent on January 9, 2012
at 4:01 am
Thanks to like it. There is still room for improvement in it and I am already planning to write next part of it. Please keep giving me the feedback to improve it further.
Regards
Zeeshan Amjad
By: Zeeshan Amjad on January 9, 2012
at 8:45 am
[...] of any interface by registering the call back method and execute it by calling DynamicInvoke method here. But there is still one problem in it that it will call all the register call back method whenever [...]
By: Using Mediator to communicate between user controls: Part 4 « Zeeshan Amjad's WPF Blog on January 9, 2012
at 8:47 pm