Sunday, December 19, 2010

Mediator for MVVMLight like the one by SachaBarber and Marlon

I am loving and using MVVMLight V3 for everything I can find. However there is one thing I feel missing in the Messenger. You can send messages of a particular type using GenericMessage<T> however you cannot send a particular message other than resorting to Magic Strings.

This is where the mediator implementation by sacha barber comes in : http://sachabarber.net/?p=477
I really like his implementation (which in turn was a simple modification of marlon's code).

I really liked that you can just signup for messages identified by a particular enum rather than a particular type (the MVVMLight way). 

However thanks to GenericMessage it was super easy to do. But first

What is a mediator
Since the view code behind should be unaware of the VM (view model). And VM should be unaware of other VMs. The only way to state something has happened is to use a Mediator (or a messenger).
More here : http://basaratali.blogspot.com/2010/12/all-you-want-to-know-to-mvvm-with.html

The Code 
All you need to modify below is add your own message enumerations:


public enum ViewModelMessages { SearchSitesStarted = 1 , SearchCellModified = 2 ,UploadSites=3,SelectUploadFile,UploadFileUpdated};
    public class GenericMessages
    {
        public ViewModelMessages MessageType { get; set; }
        public object Payload;   
    }
    public static class Mediator
    {
        public static void Send(ViewModelMessages messageType, object payload)
        {
            Messenger.Default.Send(new GenericMessages { MessageType = messageType, Payload = payload });
        }
        public static void Register(ViewModelMessages messageType, object recipient, Action<object> action)
        {
            Messenger.Default.Register(recipient, (genericMessage) =>
            {
                if (genericMessage.MessageType == messageType)
                {
                    action(genericMessage.Payload);
                }
            });
        }
    }



Sending Messages

Super easy to do:
Mediator.Send(ViewModelMessages.SearchSitesStarted, null);


Receiving Messages

Just as easy:
Mediator.Register(ViewModelMessages.SearchSitesStarted, this, (a) => { MessageBox.Show("Search Started"); });