Windows Phone From Scratch #18 – MVVM Light Toolkit Soup To Nuts 3

This is the third part of the MVVM Light Toollkit Soup To Nuts (part 1 is here) withinwhisper the Windows Phone From Scratch Mini-tutorial series.  Today we look at an introduction to messaging as a tool for communicating, e.g., from the view-model to the view.


What We’ll Build

To illustrate this, we’ll return to the example we began in part 1, and extended in part 2 (you can download the part 2 source code here).  As you’ll remember, we were able to convert the click event on the button on MainPage to be a command that is handled in Page 2. 

We stubbed out the handling of that command, but now it is time to complete the logic, by having the view model cause a navigation from MainPage to Page 2.  Unfortunately, the service that we need (NavigationService) is not available in the view model, and the easiest thing to do is to signal MainPage to make the transition. 

There is and should be no visibility of a view from a view-model, however, and so we need a mechanism for sending out a message in a bottle to be picked up by anyone who is interested. Specifically, we want the view model to be able to send a message indicating that it’s time to navigate to page 2. Further we want main page to register to receive that message, and on receipt, to invoke the navigation service to effect the transition to page 2.

Messaging

Fortunately, the MVVM Light Toolkit provides extensive support for messaging.  To accomplish our goals will require a fairly straightforward three-step process:

  1. Create a class to contain the message that is to be passed
  2. In the view model, instantiate the message class and broadcast the message
  3. Within MainPage.xaml.cs register for the message and handle it when received

Begin by creating a new class in the project in Visual Studio, and call the new class GoToPageMessage

using System;

namespace MvvmLightNavigationBehaviorAndMessages
{
   public class GoToPageMessage
   {
      public string PageName { get; set; }
   }
}

 

Return to MainViewModel.cs and remove the contents of the GoToPage2 method. Create an instance of the GoToPageMessage (initializing the PageName with the name of the page you want to navigate to) and use the Messenger object to broadcast the message, as shown here,

private object GoToPage2()
{
   var msg = new GoToPageMessage() { PageName = "Page2" };
   Messenger.Default.Send<GoToPageMessage>( msg );
   return null;
}

 

You’ll need to include the supporting library,

using GalaSoft.MvvmLight.Messaging;

 

This broadcasts the message, all that is left is to register a recipient and to respond to the message.  To do that, return to MainPage.xaml.cs, and register for the message in the constructor or in the MainPage_Loaded event handler,

Messenger.Default.Register<GoToPageMessage>
( 
     this, 
     ( action ) => ReceiveMessage( action ) 
);

 

You will need to add the Messaging using statement as well as a using statement for System.Text

ReceiveMessage is a method that you’ll write that will take the PageName and assemble a Navigate statement,

private object ReceiveMessage( GoToPageMessage action )
{
   StringBuilder sb = new StringBuilder( "/Views/" );
   sb.Append( action.PageName );
   sb.Append( ".xaml" );
   NavigationService.Navigate( 
      new System.Uri( sb.ToString(), 
            System.UriKind.Relative ) );
   return null;
}

 

Build and run the application. Clicking on the button on MainPage will now cause the application to navigate to Page 2.

So, Is This Easier??

No one would argue that what I’ve shown here is easier than simply handling the click-event in the code-behind. What I would argue is that this is easier to test because the programmer created logic is now in the view-model rather than in the code behind.

In any case, the use of behaviors and messaging goes well beyond this use-case, as we’ll see in coming tutorials.

You can download the final source code here.

Share

About Jesse Liberty

Jesse Liberty is a Master Consultant for Falafel Software, and has three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Technical Evangelist for Telerik and for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS.
This entry was posted in Data, Mini-Tutorial, Patterns & Skills, WindowsPhone and tagged . Bookmark the permalink.

23 Responses to Windows Phone From Scratch #18 – MVVM Light Toolkit Soup To Nuts 3

  1. Hello colleagues, how is the whole thing, and what you wish for to say on the topic of this paragraph, in my view
    its really remarkable for me.

  2. seo says:

    Hi there! Someone in my Myspace group shared this site with us so
    I came to give it a look. I’m definitely loving the information.
    I’m book-marking and will be tweeting this to my followers!
    Excellent blog and outstanding design.

    Here is my website … seo

  3. Jillian says:

    Awesome! Its really awesome post, I have got much clear idea about from
    this piece of writing.

  4. Pingback: Win8 (Metro style) app development – getting started « RaSor's Tech Blog

  5. Pingback: Empezando con Windows Phone 7.1 (y XV) – Navegación con MVVM Light « jdmveira

  6. Deepa says:

    I Have a requirement while navigating.

    i want to navigate from one page to the other depending on some intrenal action and not depending on the button click. How can i do this.

  7. bryan says:

    This code sample seems to work ok for my WPF app:

    NavigationService _service;
    _service = NavigationService.GetNavigationService(this);
    System.Uri uri = new System.Uri(sb.ToString(), System.UriKind.Relative);
    _service.Navigate(uri);

    • Welson says:

      but i can not achieve the effect by using your code. the error is that Object reference not set to an instance of an object.

      • Liam says:

        Your MainWindow will not have a navigation service of it’s own, simply add a frame to your xaml like this:

        Then you can use the navigation like this (vb code):

        Private Function ReceiveMessage(action As Message.GoToPageMessage) As Object
        ContentFrame.NavigationService.Navigate(New Uri(String.Format(“/View/{0}.xaml”, action.PageName), UriKind.Relative))

        Return Nothing
        End Function

        there is no need for a global _Nav or to call NavigationService.GetNavigationService(this).

  8. Bráulio says:

    Hello!

    I’m loving your walkthrough!
    However I’ve hit a road block.

    The NavigationServices doesn’t work for the WPF, which I am using.

    Is there another way to switch between views? I’ve looked everywhere for a simple tuturial and was unable to find it.

    Any sugestions? BTW, i’m reading about MEF + mvvmlight to see if that combo can help me.

    Thanks!!! :)

  9. Kevin says:

    Messaging is cool! however it is suitable for only one receiver exists. When I have multiple objects of the receiver class, all the objects receive the message, which is not correct. How could resolve this problem?

  10. Jim Boone says:

    @Jim Boone
    Please ignore this post. It was the result of a corrupted test environment. It turns out that you cannot guarentee that the View will exist to hear the message, while the Navigate method will instantiate the view if not already available.
    Jim Boone

  11. Jim Boone says:

    I’m sure I’ve committed serious violations to the “Software Developer’s Creed”, but I’ve cut out the middle-man from my implementation of this example. As I understand this example, The viewModel messages to it’s view, and in the code-behind for it’s view the message is transformed into a call to NavigationService.Navigate which then changes the displayed view.

    In building my test project, I used messages with tokens to provide a smaller scope to my event handlers. I only have one event handler that listens for messages targeted to a specific view. I put this handler on the code-behind of the targeted view where it calls NavigationService.Navigate to itself, and the targeted view is displayed.

    The advantage of doing this is I can put a payload in the message and the targeted view/viewModel will receive this payload directly.

    I stumbled into this configuration accidently, so there must be lots of reasons that this particular practice will cause problems in the future. Please explain any problems you foresee. I’m very interested in learning any downside, so if anyone is interested, I’ll create a simple test case to review.

    Jim Boone

  12. Pingback: Navigation in a #WP7 application with MVVM Light | www.nalli.net

  13. I’d just like to validate’s Laurent’s approach to navigation. It’s almost exactly the way we do things in Caliburn.Micro. One thing about messaging is that you can use it for almost anything. That’s an advantage and a disadvantage. In this case, I prefer to use a specific navigation service over messaging because the navigation concept is so central to the architecture of the application. Making that explicit through a service helps to enforce that.

    @shoaib
    Regarding query strings. One thing we do in Caliburn.Micro, which you could easily adapt into MVVM Light or any solution, is that when a page is navigated to, we parse the query string and see if any of the keys match the properties on the ViewModel. If they do, we use some reflection and type coercion to push the values into the view model. That makes working with query strings really easy.

  14. Josh says:

    Thank you so much for this series. I am totally sold on the MVVM concept but have been struggling to get started with MVVM Light. As you noted there are almost no examples that a.) are for Windows Phone 7 rather than WPF or Silverlight proper, b.) aren’t based on the CTP version of the WP7 toolkit, and c.) are simple enough to actually show how MVVM works rather than cluttering the project file with tons of app-specific code like complicated animations and data access and processing.

    In a future post, would you address how to trigger an animation in the view from the viewmodel? This seems like it’s one of the tricker aspects of MVVM and I would really like to see how it works.

  15. Shoaib Shaikh says:

    Thanks Laurent ,
    Your post is exactly what i need. Thanks alot.

  16. Bernhard K says:

    Shoaib, Navigation is the responsibility of the View and not the ViewModel anyhow, so Code Behind is perfectly fine for handling Naviation requests IMHO.

    If you want to pass Querystrings, simply extend the GoToPage with a QueryString property. You can put as much context as you want in there.

    Handling the Querystring in another VM is a little trickier … I went the easy way and just get a reference to the current ViewModel of my View by:

    MyViewModel vm = this.DataContext as MyViewModel;

    I pass all data I need in my VM from my View’s code behind wich processes the Querystring.

    But for that point … maybe Laurent or Jesse can come up with a better solution :)

    One thing I would change is that I don’t register my Messenger handler in MainView.xaml.cs but maybe directly during app startup and attaching an anonymous method or creating a separate class for handling this … as for some reason I don’t like the idea that MainView.xaml.cs handles all Navigation requests from other Views. Not because it’s code behind but I think my MainView is not responsible for other Views. :)

  17. While the messaging approach works fine, I find myself using another technique for navigation from a viewmodel. I wrote a quite detailed blog post explaining how I usually do this. See http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx

    Cheers and keep up the great work with your articles!!

    Laurent

  18. Shoaib Shaikh says:

    Very nice article really from the scratch, but is this really according to MVVM best practice to have navigation service method in code behind? and what if i need to pass some Querystring parameter while navigation? how to do that? and how to handle that Querystring parameter in another page’s ViewModel?

  19. Pingback: Tweets that mention Windows Phone From Scratch #18

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>