When developing an application, a single page usually contains many submodules. Depending on the platform, these modules are called sub Views and sub Components. In this section, we will discuss how each module interacts weakly with each other in complex business situations.

Coupling

In the image below, imagine we need to make the content change in View B when we click a button in View A.

Coupling

Two solutions immediately come to mind.

  1. View A actively sends notification to View B so View A is connected to View B.
void Notify()
{
	ViewB.Update(color);
}
  1. View B listens for a ColorChanged event and actively pulls updates. In this way, View B became dependent on View A.
ViewA.OnColorPropertyValueChanged+=(color)=>{
	Update(color);
}

Both of these implementations can be implemented without any problems. But let’s consider a complex single-page application, these strong connections would double the complexity of the program. The main idea of MVVM is independence. While View and ViewModel do not feel the presence of each other, neither ViewModel and ViewModel should.

Introducing the Mediator Model

We will use a mediator pattern to resolve this strong dependency by adding a mediator, we will make the Publisher ViewModel tell the mediaitor when its status changes, and the Subscriber ViewModel will respond to the mediator when this request comes.

Mediator Pattern

Now you must define a mediator as MessageAggregator. If this Aggregator is responsible for transmitting the messages it receives, Key is a unique id and Value is a Handler as the message to be transmitted, the basis of Aggregator will be a Dictironary data structure.

public delegate void MessageHandler<T>(object sender, MessageArgs<T> args);
public class MessageAggregator<T>
{
    private readonly Dictionary<string, MessageHandler<T>> _messages = new Dictionary<string, MessageHandler<T>>();
    public static readonly MessageAggregator<T> Instance=new MessageAggregator<T>();
   
    private MessageAggregator()
    {

    }
   
    public void Subscribe(string name, MessageHandler<T> handler)
    {
        if (!_messages.ContainsKey(name))
        {
            _messages.Add(name, handler);
        }
        else
        {
            _messages[name] += handler;
        }
    }

    public void Publish(string name, object sender, MessageArgs<T> args)
    {
        if (_messages.ContainsKey(name) && _messages[name] != null)
        {
            _messages[name](sender, args);
        }
    }
}

Making ViewModel Independent using Mediator

When we bind to the MessageAggregator object as an intermediary, the ViewModelForB becomes a Subscriber object.

MessageAggregator<object>.Instance.Subscribe("ColorChanged",ToggleHandler);

When ViewModelForA changes its state, it sends a state message to our Mediator object as Publisher.

MessageAggregator<object>.Instance.Publish("ColorChanged", this,new MessageArgs<object>("Red"));