MVVM Light Messaging

Posted on July 5, 2010 by

This entry is part 7 of 8 in the series Windows Phone 7

Since I started using the MVVM Light toolkit, I’ve gotten lots of questions about the it. In this post, I’m going to show you the basics of using the Messaging infrastructure. In the sample application attached, we have the situation where a Master page with a list of data items is trying to move to the Details page to show the details for one specific item.  There are a couple of ways to do this, but the one I’ve starting using is the Messaging infrastructure in MVVM Light. It involves the ViewModels communicating with each other via a lightly-coupled messaging bus rather than a direct coupling or using the query string.  Let’s break it down…

The sample application displays a fixed set of data elements in a list on the main page.  When an item is selected from the list, it navigates to the details page and shows the details. Presuming you already have the main page working, here’s what’s left:

Step 1 – Send the message out to the bus

When you create a new ViewModel property using the MVVM Light snippets, the sample code that gets created asks you to make a decision between publishing the PropertyChanged event to the message bus or not.  In our case, we want to publish to the message bus.  This will allow registered receivers to pick up this message. So – inside the MainViewModel, we have this property:

public Person SelectedItem
{
    get
    {
        return _selectedItem;
    }

    set
    {
        if (_selectedItem == value)
        {
            return;
        }

        var oldValue = _selectedItem;
        _selectedItem = value;

        // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
        RaisePropertyChanged(SelectedItemPropertyName, oldValue, value, true);
    }
}

The RaisePropertyChanged method includes two overrides – this one publishes to the Messaging infrastructure for us.  Now all we need is a listener…

Step 2 – Register the Details view model to listen for the appropriate message

Now that the message is getting published to the message bus, we need a receiver to pick it up and act on it.  In our case, that’s the DetailsViewModel. In the constructor for the ViewModel, we add the necessary code to register for receiving SelectedItem PropertyChanged messages like this:

public DetailsViewModel()
{
    Messenger.Default.Register<PropertyChangedMessage<Person>>(
        this,
        (action) => DispatcherHelper.CheckBeginInvokeOnUI( () => this.Item = action.NewValue )
    );
}

Notice the Register statement – we need to register for instances of the PropertyChangedMessage message that transport Person objects.  Our example is simple, so any type a PropertyChanged message is sent into the bus with a Person attached to it, the DetailsViewModel will pick it up.  If there is any disambiguation that needs to be made, there are a couple of other overrides to the Register method that allow you to provide a “token” (i.e. message name) as well as a switch to manage whether or not derived messages will also be picked up,

Since the GlobalViewModel locator creates and manages the lifetimes of our ViewModels, the DetailsViewModel is always instantiated and is available at the beginning of the application lifecycle to register for these messages.  When the messages arrive, even if we don’t navigate to the Details page, the DetailsViewModel is ready for us.

The full sample can be downloaded right here.

Series NavigationInputScopes for Windows Phone 7My “Hello World” Windows Phone 7 Application

Comments (22)

 

  1. Jeff says:

    Hi Chris,
    Your blogs have been very helpful in my learing (mind shift) to MVVM and the MVVM-Light toolkit!

    I used your example from http://chriskoenig.net/2010/07/05/mvvm-light-me… to build a similar app and learned a lot. In my app when I select an Item from the Main page and navigate to the details page everything up to that point works great. The problem happens when I use the 'Back' button on the Windows Phone 7 emulator and try to choose the same item from the main list for a second time. Nothing happens, it won't navigate to the details page because the Item is still selected and therefore the SelectionChanged event does not fire. When I tried to deselect the item, a new SelectionChanged event fires and passes a null object to the details page (results in a blank details page).

    Do you know of a way to deselect the item from the listbox (so that it can be clicked again) without triggering a new SelectionChanged event?

    Thanks in advance,
    Jeff

    • fel0niousmonk says:

      why not have your mainpageview register for the same message that the detailsview is listening to, de-selecting the item from the list …

      and then prevent a null SelectedItem from publishing the SelectionChanged message, (or prevent navigation). (you don’t want to navigate to a blank details screen, right?)

  2. Chris Koenig says:

    Thank you for your email! I am currently out of the office attending Dallas TechFest. I will return to the office on Monday – until that time, I will have limited access to email so responses will be delayed. If this is an emergency, please call my cell phone at 214-385-5616.

    Thanks!
    Chris

  3. Colin_s_johnson says:

    Where’s the source?
    Those links are both broken :(

  4. Chris Koenig says:

    I just tried it and it seems to be working OK. Give it another go.

    /ck

  5. Chris Koenig says:

    Interesting question – you could instead use the LeftMouseButtonUp event instead of SelectionChanged to track actions against the list, although that feels sort of icky to me. I will need to go back and update my sample to make sure that the navigation only happens when an item is actually selected, not when an item is deselected.

    Good catch!

    /ck

  6. Brett says:

    I’m running into the same issue. It’s driving me up a tree. Any thoughts?

  7. Geoff Hudik says:

    I didn’t like MVVM Light’s ViewModelLocator and it’s static nature – see http://blog.roboblob.com/2010/01/17/wiring-up-view-and-viewmodel-in-mvvm-and-silverlight-4-blendability-included/.

    Though now that I see without that the destination ViewModel won’t be instantiated to listen for the message

  8. Rod says:

    Hi Chris,

    I am refactoring my NON-MVVM project into MVVM and am using the MVVM Toolkit Light.

    I was just wondering WHEN to use messaging. For example, I am refactoring a non-MVVM project to MVVM – I raise a lot of events in my VM and subscribe to them in the View and change the state of certain controls (I know I should be using binding for this ultimately but it’s a big job to refactor all at once).

    Instead of the event model, should my VM be sending messages and my V receiving them? Or are messages for inter-VM comms?

    thanks

    • Chris Koenig says:

      Great question!

      The way I understand it, the way MVVM Light Messaging was intended to be used was to communicate between VMs (as my sample shows) and to communicate from the VM to the V. Since the V doesn’t explicitly hold a reference to the View I would not recommend creating one by referencing it in the code behind and attaching event handlers to it.

      Use messaging for VM to VM and VM to V communications and I think you’ll be in good shape.

      Cheers!
      Chris

  9. Rod says:

    Thanks for the explantion – one thing – you say ” If there is any disambiguation that needs to be made, there are a couple of other overrides to the Register method that allow you to provide a “token” (i.e. message name) as well as a switch to manage whether or not derived messages will also be picked up ”

    I can see the overload in Messenger.Default.Register to take in a token, but in the RaisePropertyChanged method there is only 1 overload that lets you broadcast (bool) and no way to specify the token. So I am using this to tell my chil VM to update the parent VM when a certain bool property changes, but I think the parent VM is now listening for any bool property change and fires code unneccessaryily. How can I only send the Token I want using RaisePropertyChanged and broadcast? Thanks

    • Chris Koenig says:

      Yeah – I admit that it’s not quite as simple as I describe, considering the words I chose. The Messenger object has a couple of overrides, which include a Token parameter. Instead of using the Messaging override of NotifyPropertyChange, if you want to disambiguate I think you have to manually call out to Send:

      Messenger.Default.Send(value, “MessageDisambiguator”);

      Then, in your DetailsViewModel, instead of registering for just the property change, you’d do something like this:

      Messenger.Default.Register(this, “MessageDisambiguator”, false, (title) =>
      DispatcherHelper.CheckBeginInvokeOnUI(() => Item = title));

      Hope this helps!
      Chris

  10. [...] calculator from Microsoft for cheap math geeks (tags: math software microsoft calculator windows) MVVM Light Messaging « Development « Chris Koenig (tags: silverlight mvvm light toolkit) Published Wed, Jan 12 2011 12:01 PM by [...]

  11. [...] workshops for which you can download the code, and there are some tutorials by Jesse Liberty and Chris Koenig.  That’s not too bad, but, perhaps because I prefer to learn by example, I would like to [...]

  12. Kevin Marois says:

    Chris,

    Your download from this page:
    http://chriskoenig.net/2010/07/05/mvvm-light-messaging/

    is missing a component called PhoneApplicationPage.

    Otherwise, great job. Very helpful.

    Thnaks

    • Chris Koenig says:

      Thank you for your email! I am out of the office visiting with students and speaking on Windows Phone. If your need is urgent, please feel free to call my mobile number, listed below. Otherwise, I will return your email just as soon as I can.
      Thanks!
      Chris

      Chris Koenig | +1 (214) 385-5616 | Developer Evangelist
      blog: http://chriskoenig.net/ | twitter: @chriskoenig

  13. Tim says:

    Hey Chris, did you ever find out how to solve this issue. I am experiancing this same issue, as soon as I go back the item is selected already and if I select any other item it is passed a null value.Thanks

  14. Sanal says:

    i can’t download sample because link broken

  15. [...] workshops for which you can download the code, and there are some tutorials by Jesse Liberty and Chris Koenig. That’s not too bad, but, perhaps because I prefer to learn by example, I would like to have [...]

  16. Paul says:

    Hi

    Quick question regarding navigation using this toolkit. If I have a Customers view and view model and a Customer view and view model and want to navigate to the Customer.xaml view from binding the doubleClick of my Customers datagrid, how is this do-able with messaging?

    Cheers

  17. Sven says:

    Hi,

    thanks for sahring this great article. I just came across while searching for the purpose of such a Messaging API.
    Now I understood