Posted by: Zeeshan Amjad | January 6, 2012

Using Mediator to communicate between user controls: Part 2


We saw our first cut and very naïve example of mediator here. Although it works in that example but there are several limitations in it. The biggest problem is that mediator is not reusable. Mediator contains the very hard references of two user controls so we can’t use it in any other project, even in the same project to communicate with two other user control. In that case we might end up using more than one mediator class. Not only this we are still limited to only two user control per mediator. Using the existing mediator we can’t communicate with more than two user controls at a time.

Lets first remove the dependency of any specific user control from the mediator class. We introduced one simple interface in the project. The purpose of this interface is to make a collection of classes implement that interface in the mediator. As a added bonus now we can add as many user control inside the mediator as we want. Here is a code of our interface.

Code Snippet
public interface IMediatorClient
{
    void Send(object message);

    void Notify(object message);
}

 

Here is a class diagram of it.

IMediatorClient

Now our mediator class is very simple and not specific to any user control. Here is a code of our modified mediator.

Code Snippet
public class Mediator
{
    private List<IMediatorClient> clients = new List<IMediatorClient>();

    public Mediator()
    {
    }

    public void Register(IMediatorClient client)
    {
        clients.Add(client);
    }

    public void Send(object message)
    {
        foreach (var client in clients)
        {
            client.Notify(message);
        }
    }
}

 

Note that we are no more accepting the user control in constructor of the mediator. But we introduced a Register method and the whole purpose of the register method is to create a list of all classes that implement IMediatorClient interface.

Send function is very simple. We just iterate through all the register classes and call Notify method of every class.

We have to change the code of main window class little bit. In our main window class, now we are registering the user control one by one. It is important that no matter how many user control do we have, message will be send to only those classes which are register in the mediator. Here is a complete code of our main window.

Code Snippet
using System.Collections.ObjectModel;
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);
            Mediator.Register(studentlist);

            studentform.Mediator = Mediator;
            studentlist.Mediator = Mediator;

            DataContext = students;
        }
    }
}

 

Now the last missing part is to implement the IMediatorClient interface to both user control. This step is quite straight forward, because we already have Send and Notify method implemented in these controls. Here is a complete code for CustomizedList user control.

Code Snippet
using System.Windows;
using System.Windows.Controls;

namespace MediatorUserControl
{
    /// <summary>
    /// Interaction logic for CustomizedList.xaml
    /// </summary>
    public partial class CustomizedList : UserControl, IMediatorClient
    {
        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 complete code of StudentForm user control.

Code Snippet
using System.Windows.Controls;

namespace MediatorUserControl
{
    /// <summary>
    /// Interaction logic for StudentForm.xaml
    /// </summary>
    public partial class StudentForm : UserControl, IMediatorClient
    {
        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;
            }
        }
    }
}

 

This relationship can be shown by this diagram.

mediator_02

The output and functionality of this program is exactly same as previous program. But this program has one advantage that now we can reuse the mediator class in any other project and can use with more than two user controls. Here is a the output of the program.

mediator_02_output

Advertisements

Responses

  1. Is that code available for download

    • Hi Hassan

      I couldn’t able to upload files here. I am looking at other options to upload the code, may be at skydrive and give link to here. But i can email you the project code of part 3 of the article.

      Regards
      Zeeshan Amjad

  2. […] 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 […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: