Universal App Tutorials Part 10 : MVVM Light NavigationService

Navigation

Despite the rise in popularity of Single Page Applications (SPAs) and supporting frameworks like Angular in the Web Development world, it might be nice if we had more than one page in our app, or at least had the option to.  Our app so far is contained within a single page, MainPage.xaml.  A common pattern is to have different pages for Settings or Publisher contact information.  Navigation has moved on since Windows Phone 7.5 when it was URI based, we will look at how it now works with Universal Apps with typing and the MVVM Light implementation of INavigationService.

Outcome

We’ll look to add an (empty for now) About Page to our project, and look at how we can navigate to it, along with cleaning up our solution slightly along the way.  We’ll be using the INavigationService interface and the MVVM Light implementation of the NavigationService class to swap between our pages.

Prerequisites

Implementation

Refactoring

Let’s start by creating a folder for our Views in which our Pages will reside.  In doing this we will also look to push our existing view into a MorseCoder.Views Namespace.  Create a Views Folder at the Morse Coder root, and move MainPage.xaml into it.  Ensure it builds, no reason it shouldn’t at this stage.

Views with MainPage.xaml under Morse Coder Root
Morse Coder Structure with Views Folder

Now let’s move the Namespace for completeness and personal preference, you could skip this and it will work just fine.  Let’s start with the Code Behind:

using Windows.UI.Xaml.Controls;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace MorseCoder.Views
{
///
<summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>

public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
}

…and move onto the xaml page:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MorseCoder.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:UserControls="using:MorseCoder.UserControls" x:Class="MorseCoder.Views.MainPage" mc:Ignorable="d" DataContext="{Binding Main, Source={StaticResource Locator}}">

Note the change of the local namespace and the class the page is associated with.

If you try to build now it should fail.  Currently, the only reference to the MainPage class is in the App.xaml.cs class which we haven’t really encountered as yet.  At a very high level the App.xaml.cs class manages your application’s lifecycle and importantly in our case, tells your app where to go on start up.

All we need to do is add a using MorseCoder.Views declaration to get things moving again:

Using-MorseCoder.Views_.png

About Page

Let’s create an empty page to house our details just like in Morse Coder Part 1.  Call it AboutPage.xaml and create it in our newly created Views Folder.  We’ll look to flesh the content of this page in a future tutorial.

INavigationService

The INavigationService will be dependency injected into our View Models in exactly the same way that we learned about in Morse Coder Part 4, we will be creating an instance of the NavigationService, registering it with our IoC container (SimpleIoC), and then requesting it through the constructor of the ViewModel to make it accessible across our App.  Let’s look at this closer.

Create a static method on the ViewModelLocator to create an INavigationService object for us.  This will also encapsulate the definition of what pages are available to our app and save the ViewModelLocator constructor from getting bloated:

private static INavigationService CreateNavigationService()
{
INavigationService navigationService = new NavigationService();

navigationService.Configure("About", typeof(AboutPage));

return navigationService;
}

Now we can use this to create an instance of INavigationService in our ViewModelLocator Constructor, let’s register it:

static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

INavigationService navigationService = CreateNavigationService();
SimpleIoc.Default.Register<INavigationService>(() => navigationService);

SimpleIoc.Default.Register<MainViewModel>();

...
}

Add the appropriate namespaces as using Statements and ensure your app builds.

Consume the INavigationService from MainViewModel

Follow the pattern followed for the IMorseCoderSettings interface and request INavigationService from the MainViewModel constructor.

public class MainViewModel : ViewModelBase
{
private ITranslator _translator;
private IMorseCoderSettings _morseCoderSettings;
private INavigationService _navigationService;

...

public MainViewModel(IMorseCoderSettings morseCoderSettings, INavigationService navigationService)
{
_morseCoderSettings = morseCoderSettings;
_navigationService = navigationService;

...
}
}

Navigation Relay Commands

We’re now ready to consume our Navigation Service from a relay command which we can then wire up to a button.  Create an AboutNavigateCommand RelayCommand object as in Morse Coder Part 7, and an associated AboutNavigateCommandAction:

public RelayCommand AboutNavigateCommand { get; private set; }

private void AboutNavigateCommandAction()
{
_navigationService.NavigateTo("About");
}

…and instantiate the AboutNavigateCommand in the MainViewModel constructor:

AboutNavigateCommand = new RelayCommand(AboutNavigateCommandAction);

The consumption of the Navigation Service is very straight forward.  It would be sensible to avoid a potential ‘gotcha’ and implement a set of constants for our page name keys, you may have noticed that we’ve used a string in both the definition and navigation to our Page.

Button

Add an About Button to our view, don’t worry too much about where you put it, we’re due a clean up of our MainPage at some point!  Bind our Command to the Command property on our button and let’s test it:

AboutButton.png

About Page:

EmptyAboutPage.png

Here’s our about page, it’s very much empty at the moment, but at least we can get to it!

Summary

Where are we?

  • We created an instance of and configured the MVVM Light Navigation Service;
  • We registered it with the IoC container and used it from the MainViewModel;
  • We created a button and wired up a navigation command to the newly created About Page.

Where are we heading?

We’ll look at:

  • adding some more functionality to the app to swap the translation direction;
  • adding some functionality to our clean slate About Page;
  • methods of serialising POCOs to Application Settings.

1 thought on “Universal App Tutorials Part 10 : MVVM Light NavigationService”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s