In this post I'll talk about the Messenger utility in the MVVM Light Toolkit. The other posts in this series are as follows (I'll update this list as they are published):
- Silverlight, MVVM & SharePoint - About this Series...
- Silverlight, MVVM & SharePoint - How I do MVVM
- Silverlight, MVVM & SharePoint - My favorite MVVM toolkit - MVVM Light Toolkit
- Silverlight, MVVM & SharePoint - Working with Commands
- Silverlight, MVVM & SharePoint - Working with Messages
- Silverlight, MVVM & SharePoint - Working with Dialogs
- Silverlight, MVVM & SharePoint - Testing the Business Logic
- Silverlight, MVVM & SharePoint - Testing the User Interface
- Silverlight, MVVM & SharePoint - Using Data Services
Most of the stuff in the MVVM Light Toolkit addresses things to simplify common things you have to deal with such as commands, view models and declaratively binding a new instance of a view model to a view's data context.
One thing that is a "new feature" included in the toolkit is this special class called a Messenger. What this does is that it allows you to broadcast messages from anywhere in your application as a typed object and have another place in your application listen for those messages. This comes in very handy when working with dialogs, something I'll address in a different post. There are a few different types of messages that the Messenger supports such as:
- NotificationMessage: used to send a notification to the registered recipients. There is an associated message that also lets you pass in an action for some code to be executed in the callback by the recipient.
- DialogMessage: used to send a notification to a recipient that a dialog should be launched. I'll explain how I use these in another post.
- PropertyChangedMessage: used to broadcast & receive notifications that a property changed.
- MessageBase & GenericMessage: good when you want to create your own type of message that doesn't fall into the above categories.
Great you say... how do I use this? I use it a few different ways. As I said I'll talk about the dialog message in the next post. Let me walk through a few of them in my Product Browser reference implementation (RI).
When I go to save an item, I'm doing it async because it's happening against an OData service. What I'd like to do is tell the UI "I'm working, let the user know that and ask them to wait". To do this I use the IsBusy control from the Silverlight Toolkit on CodePlex. To do this I need to broadcast across my app that this action is happening. From within the main view model I want to listen for this and change a few things, specifically an object I use to turn on/off the IsBusy indicator and to display a specific message.
What happens is that I use a command to fire off an edit dialog for the user to edit a specific command when a button is clicked. When the dialog is closed, if the user clicked OK (instead of cancel), I first want to broadcast the message (on line 249 below) that will change the busy state and save the product:
So what happens when a property changes? The XAML UI listens for properties to change and refreshes UI controls when objects bound to them changes. But what if you want to do something... say for instance when a category is selected, you want to fill up the matching products collection to have that be shown in the UI? This is where the PropertyChangedMessage comes in handy.
When a new product category is selected, using data binding it updates an object in the view model as the following two screenshots show. Notice in the property on line 175 where I'm calling RaisePropertyChanged() which is part of the ViewModelBase that comes with the toolkit? That last Boolean option says "broadcast this message across the app".
The next part is that I need to listen for this message and when I see it, I need to update the matching products. When the view model is created the constructor calls a method RegisterMessages() where I create a few messages, such as the following one:
This says the following:
- Listen for messages of type PropertyChangedMessage and make sure the object in the payload of the message is of type ProductCategory.
- When you see a message get broadcast like that, check if it is a specific property, specifically the one that has the name of SelectedProductCategory.
- If it is, call the method LoadProducts().
LoadProducts() async gets all matching products and loads them into a collection and broadcasts to the UI that the property changed. This triggers the Silverlight UI to refresh the listbox that contains a list of all the product categories.
Pretty slick! In the next post I'll talk about how I handle dialogs.