Friday 3 October 2014

Navigation in MVVM Light using Messenger

There are a few ways to implement navigation in MVVM Light based application. One of them is to use the Messaging framework of the toolkit. We will see a simple example of how to do this on Windows Phone.

1. First, in our view, we need to register to listen for a message that we want to receive :
Messenger.Default.Register<uri>(
this,
"MyToken",
(uri) => NavigationService.Navigate(uri)
);
We can put this in the view constructor or OnNavigatedTo() method. This code is saying that I want to register to receive any message that delivers uri type that uses 'MyToken' token. If there is any then I will execute an action which in this case is calling NavigationService.Navigate(uri).


2. Then in the view model, we need to create a command to trigger the message that will be broadcasted.
We add a RelayCommand property for a navigation command:
public RelayCommand NavigateCommand { get; private set; }
Then in the view model constructor we initialise that (or could be on the property getter above):
NavigateCommand = new RelayCommand(() =>
{
Messenger.Default.Send<uri>(new Uri("/PageName.xaml", UriKind.Relative), "MyToken");
});


3. Finally bind the command property to a control on the view xaml file using:
Command="{Binding NavigateCommand}"


Soon we will have many repetitive codes in our views, so we could put the codes to register for the message in a base class like this:
public class BasePage : PhoneApplicationPage
{
 protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
 {
 Messenger.Default.Register<uri>(this, "MyToken", uri => NavigationService.Navigate(uri));
 base.OnNavigatedTo(e);
 }

 protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
 {
 Messenger.Default.Unregister<uri>(this);
 base.OnNavigatedFrom(e);
 }
}
So we just need to make our views inherit from this class.

On our xaml files, we also need to replace
<phone:PhoneApplicationPage
to
<phone:BasePage

and also
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
to
xmlns:phone="clr-namespace:YourNamespace"


Another way to do navigation is by creating our custom navigation service to be used in our view models. This nice article, explains how to implement it in details.

No comments: