Navigation in a #WP7 application with MVVM Light

In MVVM applications, it can be a bit of a challenge to send instructions to the view (for example a page) from a viewmodel. Thankfully, we have good tools at our disposal to help with that.

In his excellent series “MVVM Light Toolkit soup to nuts”, Jesse Liberty proposes one approach using the MVVM Light messaging infrastructure. While this works fine, I would like to show here another approach using what I call a “view service”, i.e. an abstracted service that is invoked from the viewmodel, and implemented on the view.

Multiple kinds of view services

In fact, I use view services quite often, and even started standardizing them for the Windows Phone 7 applications I work on. If there is interest, I will be happy to show other such view services, for example

  • Animation services, responsible to start/stop animations on the view.
  • Dialog service, in charge of displaying messages to the user and gathering feedback.
  • Navigation service, in charge of navigating to a given page directly from the viewmodel.

In this article, I will concentrate on the navigation service.

The INavigationService interface

In most WP7 apps, the navigation service is used in quite a straightforward way. We want to:

  • Navigate to a given URI.
  • Go back.
  • Be notified when a navigation is taking place, and be able to cancel.

The INavigationService interface is quite simple indeed:

public interface INavigationService
{
    event NavigatingCancelEventHandler Navigating;
    void NavigateTo(Uri pageUri);
    void GoBack();
}

Obviously, this interface can be extended if necessary, but in most of the apps I worked on, I found that this covers my needs.

The NavigationService class

It is possible to nicely pack the navigation service into its own class. To do this, we need to remember that all the PhoneApplicationPage instances use the same instance of the navigation service, exposed through their NavigationService property. In fact, in a WP7 application, it is the main frame (RootFrame, of type PhoneApplicationFrame) that is responsible for this task. So, our implementation of the NavigationService class can leverage this.

First the class will grab the PhoneApplicationFrame and store a reference to it. Also, it registers a handler for the Navigating event, and forwards the event to the listening viewmodels (if any).

Then, the NavigateTo and the GoBack methods are implemented. They are quite simple, because they are in fact just a gateway to the PhoneApplicationFrame.

The whole class is as follows:

public class NavigationService : INavigationService
{
    private PhoneApplicationFrame _mainFrame;

    public event NavigatingCancelEventHandler Navigating;

    public void NavigateTo(Uri pageUri)
    {
        if (EnsureMainFrame())
        {
            _mainFrame.Navigate(pageUri);
        }
    }

    public void GoBack()
    {
        if (EnsureMainFrame()
            && _mainFrame.CanGoBack)
        {
            _mainFrame.GoBack();
        }
    }

    private bool EnsureMainFrame()
    {
        if (_mainFrame != null)
        {
            return true;
        }

        _mainFrame = Application.Current.RootVisual as PhoneApplicationFrame;

        if (_mainFrame != null)
        {
            // Could be null if the app runs inside a design tool
            _mainFrame.Navigating += (s, e) =>
            {
                if (Navigating != null)
                {
                    Navigating(s, e);
                }
            };

            return true;
        }

        return false;
    }
}

Exposing URIs

I find that it is a good practice to expose each page’s URI as a constant. In MVVM Light applications, a good place to do that is the ViewModelLocator, which already acts like a central point of setup for the views and their viewmodels.

Note that in some cases, it is necessary to expose the URL as a string, for instance when a query string needs to be passed to the view. So for example we could have:

public static readonly Uri MainPageUri = new Uri("/MainPage.xaml", UriKind.Relative);
public const string AnotherPageUrl = "/AnotherPage.xaml?param1={0}&param2={1}";

Creating and using the NavigationService

Normally, we only need one instance of the NavigationService class. In cases where you use an IOC container, it is easy to simply register a singleton instance. For example, I am using a modified version of a super simple IOC container, and so I can register the navigation service as follows:

SimpleIoc.Register<INavigationService, NavigationService>();

Then, it can be resolved where needed with:

SimpleIoc.Resolve<INavigationService>();

Or (more frequently), I simply declare a parameter on the viewmodel constructor of type INavigationService and let the IOC container do its magic and inject the instance of the NavigationService when the viewmodel is created.

On supported platforms (for example Silverlight 4), it is also possible to use MEF. Or, of course, we can simply instantiate the NavigationService in the ViewModelLocator, and pass this instance as a parameter of the viewmodels’ constructor, injected as a property, etc…

Once the instance has been passed to the viewmodel, it can be used, for example with:

NavigationService.NavigateTo(ViewModelLocator.ComparisonPageUri);

Testing

Thanks to the INavigationService interface, navigation can be mocked and tested when the viewmodel is put under unit test. Simply implement and inject a mock class, and assert that the methods are called as they should by the viewmodel.

Conclusion

As usual, there are multiple ways to code a solution answering your needs. I find that view services are a really neat way to delegate view-specific responsibilities such as animation, dialogs and of course navigation to other classes through an abstracted interface. In some cases, such as the NavigationService class exposed here, it is even possible to standardize the implementation and pack it in a class library for reuse. I hope that this sample is useful!

Happy coding.

Laurent

 

Print | posted on Thursday, January 06, 2011 11:35 PM

Feedback

# re: Navigation in a #WP7 application with MVVM Light

left by Ian Randall at 1/7/2011 3:57 AM Gravatar
Great idea Laurent. I find kicking off animations, in particular, something that's much easier in MVP than MVVM - this is a nice solution.

BTW - As a super-simple WP7 IoC container, check out MicroIoc on http://microioc.codeplex.com/ - would love your feedback :)

Ian Randall

# re: Navigation in a #WP7 application with MVVM Light

left by Shoaib Shaikh at 1/7/2011 8:52 AM Gravatar
Great Post, a nice addition to MVVMLight resources.
You have created an event Navigating which is triggered when we leave a page. can i use it in place of View's OnNavigateFrom Method?

# re: Navigation in a #WP7 application with MVVM Light

left by Paulo Quicoli at 1/7/2011 10:54 AM Gravatar
Please, show us the other services you have :) I was used to Julmar.MvvmHelpers, and there are some services in it. When we moved to MvvmLight, we missed them...

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent at 1/7/2011 11:55 AM Gravatar
@Ian: Hi Ian,

MicroIOC looks good, thanks for sharing. The one I mentioned is really super simple, it's in fact just one class. I am probably going to integrate that in MVVM Light, but of course people are free to switch to anything they prefer (and in fact, they probably should, given that the SimpleIOC is quite limited in its abilities).

Cheers,
Laurent

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent Bugnion at 1/7/2011 12:00 PM Gravatar
@Shoaib: Hi Shoaib,

In general, it is better to use the overrides OnNavigate methods, because it saves you from having to unregister the event handlers to avoid memory leaks. However, having access to the Navigating event can prove useful in some cases.

Makes sense?
Cheers,
Laurent

# re: Navigation in a #WP7 application with MVVM Light

left by Rich at 1/8/2011 9:11 PM Gravatar
Hi Laurent,
Any chance you could throw this in to a quick sample and share it?

Thanks,
Rich

# re: Navigation in a #WP7 application with MVVM Light

left by Oliver at 1/8/2011 9:38 PM Gravatar
Great article. I'm enjoying the tutorials around MVVM Light by Jesse Liberty and this Navigation ViewService. I would also like to see your approach to the animation ViewService as well - Jesse's earlier tutorial does this in the view and I'd like to keep it closer to NavigationService described above.

# re: Navigation in a #WP7 application with MVVM Light

left by Matthew at 1/10/2011 5:38 PM Gravatar
I second the request for a sample. Also, can you provide more detail on how you instantiate the NavigationService? IOC is still greek to me. Lastly, how about passing parameters to pages as you imply in your AnotherPageUrl variable above?

Thanks!

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent Bugnion at 1/11/2011 9:00 AM Gravatar
Hi all,

Alright, lots of interest for a sample. I will make one asap and post on the blog, so stay tuned :)

Cheers,
Laurent

# re: Navigation in a #WP7 application with MVVM Light

left by Raf at 1/13/2011 8:19 PM Gravatar
Very useful and good article. I have one question if you don't mind. How do you inform ViewModel about NavigatedTo evnt? My idea is to use Messenger in OnNavigatedTo (code behind xaml file) method to send message to ViewModel. Is it ok?

# re: Navigation in a #WP7 application with MVVM Light

left by supernsetips complaints at 1/17/2011 1:07 PM Gravatar
Well after searching the countless blogs i reached your blog and i must say that your blog is awesome its really very very informative.Keep it up buddy.

http://supernsetips-news.blogspot.com



i will love to visit your blog regularly

========------------==========

# re: Navigation in a #WP7 application with MVVM Light

left by michael at 1/20/2011 3:35 PM Gravatar
Laurent,

Any chance of showing an example of this in Silverlight?

# re: Navigation in a #WP7 application with MVVM Light

left by Terry at 1/25/2011 12:45 AM Gravatar
Laurent,
I am also expect an example eagerly. Thank you!

# re: Navigation in a #WP7 application with MVVM Light

left by Ant at 1/30/2011 4:24 AM Gravatar
Hi Laurent!

I too would love to see a example :)

Thanks again,
Ant

# re: Navigation in a #WP7 application with MVVM Light

left by Scott Silvi at 2/1/2011 11:21 PM Gravatar
Here's me adding my vote to a sample, specifically in SL4. Deadlines dictate I'll have to hack something together now, but future projects would definitely benefit :)

# re: Navigation in a #WP7 application with MVVM Light

left by Rich at 2/2/2011 8:40 AM Gravatar
I'd settle for details on the modified version of the IOC container.

# re: Navigation in a #WP7 application with MVVM Light

left by Dirk at 2/13/2011 1:41 PM Gravatar
I'm able to use your example of creating a NavigationService. But I'm not able to get the parameter param1, param2
from
public const string AnotherPageUrl = "/AnotherPage.xaml?param1={0}&param2={1}";
into my AnotherPageViewModel.
Do you have a small hint?

# re: Navigation in a #WP7 application with MVVM Light

left by phertzog at 2/24/2011 1:21 AM Gravatar
Nice post. Can you publish an example using the OnNavigateFrom override? I'm not sure to get the way you would link it to the ViewModel? In the code behind?

In every case thanks for this nice toolkit.

# re: Navigation in a #WP7 application with MVVM Light

left by peter at 3/4/2011 9:11 AM Gravatar
Hello Laurent,

Can you publish a sample of your navigation service?

Thank you,

# re: Navigation in a #WP7 application with MVVM Light

left by Josorg at 3/4/2011 11:25 AM Gravatar
Yes ! Please a sample ;)

# re: Navigation in a #WP7 application with MVVM Light

left by Shawn Featherly at 3/7/2011 8:43 PM Gravatar
The part that tripped me up was what to do with the INavigationService variable in the ViewModel's constructor. Using it as the execute of a RelayCommand similar to how it is done in Jessie's linked article works well.

public RelayCommand GoToPage2Command { get; private set; }
public MainViewModel(INavigationService navSer)
{
GoToPage2Command = new RelayCommand(() => navSer.NavigateTo(ViewModelLocator.Page2Uri));
}

You'll need to change the CreateMain() in your ViewModelLocator.cs to set navSer.
if (_main == null)
{
_main = new MainViewModel(IoC.Resolve<INavigationService>());
}

@Rich, the modification to IoC is only in the second file:
public static partial class IoC
{
static partial void RegisterAll()
{
Register<INavigationService, NavigationService>();
}
}

# re: Navigation in a #WP7 application with MVVM Light

left by Rich at 3/12/2011 10:28 AM Gravatar
Shawn,
That was exactly what I needed. Thanks!

# re: Navigation in a #WP7 application with MVVM Light

left by Obalix at 3/18/2011 12:29 PM Gravatar
For Silverlight apllication a sample implementation can be found at http://blogs.msdn.com/b/ukadc/archive/2010/10/05/silverlight-navigation-with-the-mvvm-pattern.aspx.

# re: Navigation in a #WP7 application with MVVM Light

left by Fredrik at 3/21/2011 1:26 PM Gravatar
Hi Laurent !!!

If you have time can you post an example of your dialogservice?

Regards

Fredrik

# re: Navigation in a #WP7 application with MVVM Light

left by Makni at 3/23/2011 10:00 AM Gravatar
Yes ! We all need/want a sample of your navigation service or a MVVM Light Toolkit reference application ;).

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent Bugnion at 3/23/2011 10:35 AM Gravatar
Hey guys,

Well what I can say is: Watch out for MIX11. My session Deep Dive MVVM has demos of a few "view services" including a complete navigation sample for SL4 and WP7, DialogService, etc. I will of course post the whole code on this blog after the session.

Cheers and thanks so much for the feedback!
Laurent

# re: Navigation in a #WP7 application with MVVM Light

left by Peter at 6/16/2011 10:52 AM Gravatar
Thank you Laurent.
Is this source code available? (WP7 with NavigationService, DialogService, etc.)?

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent at 6/16/2011 11:13 AM Gravatar
Sure:
http://geekswithblogs.net/lbugnion/archive/2011/04/13/deep-dive-mvvm-samples-mix11-deepdivemvvm.aspx

# re: Navigation in a #WP7 application with MVVM Light

left by Gustavo at 1/16/2012 7:29 AM Gravatar
Would be awesome if we had a concrete simple example.

# re: Navigation in a #WP7 application with MVVM Light

left by Laurent at 1/16/2012 8:42 AM Gravatar
Concrete, simple example is available at http://geekswithblogs.net/lbugnion/archive/2011/04/13/deep-dive-mvvm-samples-mix11-deepdivemvvm.aspx

Cheers,
Laurent

# re: Navigation in a #WP7 application with MVVM Light

left by Gustavo at 1/18/2012 7:01 PM Gravatar
Thanks ! Sorry, saw that after I kept reading :).
Awesome job by the way.

# re: Navigation in a #WP7 application with MVVM Light

left by Panda at 4/1/2012 4:53 AM Gravatar
How can i do the same thing with WPF application?Please,help

# re: Navigation in a #WP7 application with MVVM Light

left by rcfliers at 11/17/2012 12:12 AM Gravatar
Hi Laurent,

I'm using the navigation service in a WPF application, I adapted what you had to WPF, and for the longest time, I was passing in my Windows ._mainFrame to my navigation services constructor. Needless to say that's a pain, but for the life of me I can't figure out how to get the _mainFrame property any other way in WPF. Any Suggestions?
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: