How to Use Cimbalino Windows Phone Toolkit - NavigationService

Introduction

The Cimbalino Windows Phone Toolkit delivers a set of useful and powerful MVVM-compatible tools and services to help developers build Silverlight applications for Windows Phone. The Toolkit is divided in projects which deliver various features, ranging from base MVVM services and helpers, through to code for background agents and for accessing media library, location services and so on. The base project (Cimbalino.Phone.Toolkit) contains base MVVM services, some very useful converters, helper classes and extension methods.

The Cimbalino NavigationService provides methods, properties and events to support navigation within an XAML application. In effect it is and abstraction of the normal System.Windows.Navigation.NavigationService, adding things like a QueryString property to return a dictionary of parameters passed to the page on navigation.

The kit provides both the INavigationService interface and its implementation NavigationService required to register the service in MVVM Light (note that MVVM and the MVVM Light Toolkit are not "preconditions" to use this service). One advantage of the service approach is that it is possible to unit test the navigation code.

This code example shows a basic MVVM Light app which uses the NavigationService to launch a page without parameters or launch a different page and display the parameters sent.

Screenshots of the example app are shown below.

cimbalino sample

Example app main screen.

app main screen

Page launched (no parameter).

Page launched

Page launched (with parameter).

Building Code Example

The source code for the code example is available here: NavigationService Example (github).
To build the source code you will also need the MVVM Light Toolkit and the Cimbalino Windows Phone Toolkit. Their packages are available in the Nuget Package Manager.

Registering the service

Register the service in the ViewModelLocator constructor as shown below (ViewModelLocator.cs).

  1. public class ViewModelLocator  
  2. {  
  3.     public ViewModelLocator()  
  4.     {  
  5.         ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);  
  6.   
  7.         if (!SimpleIoc.Default.IsRegistered<INavigationService>())  
  8.         {  
  9.             SimpleIoc.Default.Register<INavigationService, NavigationService>();  
  10.         }  
  11.   
  12.         SimpleIoc.Default.Register<MainViewModel>();  
  13.         SimpleIoc.Default.Register<Page2ViewModel>();  
  14.     }  
  15.   
  16.     public MainViewModel MainViewModel  
  17.     {  
  18.         get  
  19.         {  
  20.             return ServiceLocator.Current.GetInstance<MainViewModel>();  
  21.         }  
  22.     }  
  23.   
  24.     public Page2ViewModel Page2ViewModel  
  25.     {  
  26.         get  
  27.         {  
  28.             return ServiceLocator.Current.GetInstance<Page2ViewModel>();  
  29.         }  
  30.     }  
Note how we also define properties for the two ViewModels (MainViewModel and Page2ViewModel) and register them.

In the next section we see that the MainViewModel constructor takes a INavigationService parameter. When ViewModelLocator creates the view model it recognises that the parameter is registered, creates an instance of the NavigationService and passes it to MainViewModel.

Implementing the ViewModel

Implement the MainViewModel as shown below. The highlighted sections show the MainViewModel constructor taking theINavigationService parameter and assigning it to a private member. Later on the member is used to call NavigateTo() in order to navigate to the second page (both with and without parameters being passed).
  1. using System;  
  2. using System.Windows.Input;  
  3.   
  4. using Cimbalino.Phone.Toolkit.Services;  
  5. using GalaSoft.MvvmLight.Command;  
  6.   
  7.   
  8. /// This class contains properties that the main View can data bind to.  
  9. public class MainViewModel : ViewModelBase  
  10. {  
  11.     /// The navigation service.  
  12.     private readonly INavigationService _navigationService;  
  13.   
  14.     /// Initializes a new instance of the MainViewModel class.  
  15.     public MainViewModel(INavigationService navigationService)  
  16.     {  
  17.         _navigationService = navigationService;  
  18.         NavigateWithoutParameterCommand = new RelayCommand(NavigateWithoutParameter);  
  19.         NavigateWithParameterCommand = new RelayCommand(NavigateWithParameter);  
  20.     }  
  21.   
  22.   
  23.     /// Gets the navigate without parameter command.  
  24.     public ICommand NavigateWithoutParameterCommand { getprivate set; }  
  25.   
  26.     /// Gets the navigate with parameter command.  
  27.     public ICommand NavigateWithParameterCommand { getprivate set; }  
  28.   
  29.     /// Navigates the without parameter.  
  30.     private void NavigateWithoutParameter()  
  31.     {  
  32.         _navigationService.NavigateTo(new Uri("/Page1.xaml", UriKind.Relative));  
  33.     }  
  34.   
  35.     /// Navigates the with parameter command.  
  36.     private void NavigateWithParameter()  
  37.     {  
  38.         _navigationService.NavigateTo(new Uri("/Page2.xaml?parameter=1", UriKind.Relative));  
  39.     }  
  40. }  
The second view model Page2ViewModel is similar. Again the constructor takes the INavigationService parameter and assigning it to a private member. In this case though we call CanGoBack() and GoBack() methods to return to the original page. The highlighted line below shows a property for getting the parameter as a string.
  1. using System.Windows.Input;  
  2.   
  3. using Cimbalino.Phone.Toolkit.Services;  
  4.   
  5. using GalaSoft.MvvmLight;  
  6. using GalaSoft.MvvmLight.Command;  
  7.   
  8. public class Page2ViewModel : ViewModelBase  
  9. {  
  10.     /// The navigation service  
  11.     private readonly INavigationService _navigationService;  
  12.   
  13.     /// Initializes a new instance of thePage2ViewModel  
  14.     /// "navigationService is the navigation service.  
  15.     public Page2ViewModel(INavigationService navigationService)  
  16.     {  
  17.         _navigationService = navigationService;  
  18.         GoBackCommand = new RelayCommand(GoBack);  
  19.     }  
  20.   
  21.   
  22.     /// Gets the parameter.  
  23.     public string Parameter  
  24.     {  
  25.         get  
  26.         {  
  27.             return _navigationService.QueryString["parameter"].ToString();  
  28.         }  
  29.     }  
  30.   
  31.     /// Gets a value indicating whether [can go back].  
  32.     ///   true if [can go back]; otherwise false  
  33.     public bool CanGoBack   
  34.     {  
  35.         get  
  36.         {  
  37.           return _navigationService.CanGoBack;  
  38.         }  
  39.     }  
  40.   
  41.     /// Gets the go back command.  
  42.     public ICommand GoBackCommand { getprivate set; }  
  43.   
  44.   
  45.     /// Go back  
  46.     private void GoBack()  
  47.     {  
  48.         _navigationService.GoBack();  
  49.     }  
  50. }  
Implementing the views

The rest of the app is "plumbing" to hook up the ViewModels to the View and to send commands from the UI to the invoke the navigation service. How to use MVVM Light Toolkit for Windows Phone explains most of what is going on, but for completeness the MainPage.xaml is as shown below:
  1. <phone:PhoneApplicationPage x:Class="CimbalinoSample.MainPage"  
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  
  7.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"  
  8.                             DataContext="{Binding MainViewModel,  
  9.                                                   Source={StaticResource Locator}}"  
  10.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"  
  11.                             FontSize="{StaticResource PhoneFontSizeNormal}"  
  12.                             Foreground="{StaticResource PhoneForegroundBrush}"  
  13.                             Orientation="Portrait"  
  14.                             SupportedOrientations="Portrait"  
  15.                             shell:SystemTray.IsVisible="True"  
  16.                             mc:Ignorable="d">  
  17.    
  18.     <!--  LayoutRoot is the root grid where all page content is placed  -->  
  19.     <Grid x:Name="LayoutRoot" Background="Transparent">  
  20.         <Grid.RowDefinitions>  
  21.             <RowDefinition Height="Auto" />  
  22.             <RowDefinition Height="*" />  
  23.         </Grid.RowDefinitions>  
  24.    
  25.         <!--  TitlePanel contains the name of the application and page title  -->  
  26.         <StackPanel x:Name="TitlePanel"  
  27.                     Grid.Row="0"  
  28.                     Margin="12,17,0,28">  
  29.             <TextBlock Margin="12,0"  
  30.                        Style="{StaticResource PhoneTextTitle2Style}"  
  31.                        Text="Cimbalino Sample" />  
  32.             <TextBlock Margin="9,-7,0,0"  
  33.                        Style="{StaticResource PhoneTextTitle2Style}"  
  34.                        Text="NavigationService" />  
  35.         </StackPanel>  
  36.    
  37.         <!--  ContentPanel - place additional content here  -->  
  38.         <Grid x:Name="ContentPanel"  
  39.               Grid.Row="1"  
  40.               Margin="12,0,12,0">  
  41.             <Button Height="120"  
  42.                     Margin="0,120,0,404"  
  43.                     Command="{Binding NavigateWithoutParameterCommand}"  
  44.                     Content="Navigate without parameter" />  
  45.             <Button Height="120"  
  46.                     Margin="0,50,0,0"  
  47.                     Command="{Binding NavigateWithParameterCommand}"  
  48.                     Content="Navigate with parameter" />  
  49.         </Grid>  
  50.     </Grid>  
  51. </phone:PhoneApplicationPage>  
The first highlighted lines show binding the MainViewModel as a DataContext for the page.
  1. DataContext="{Binding MainViewModel,   
  2. Source={StaticResource Locator}}"  
The second highlighted lines bind to the RateCommands in the MainViewModel that cause the navigation methods to be called.

Page1.xaml is shown below. This page is launched without any parameters and doesn't have a view model because it needs no data.
  1. <phone:PhoneApplicationPage x:Class="CimbalinoSample.Page1"  
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  
  7.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"  
  8.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"  
  9.                             FontSize="{StaticResource PhoneFontSizeNormal}"  
  10.                             Foreground="{StaticResource PhoneForegroundBrush}"  
  11.                             Orientation="Portrait"  
  12.                             SupportedOrientations="Portrait"  
  13.                             shell:SystemTray.IsVisible="True"  
  14.                             mc:Ignorable="d">  
  15.    
  16.     <!--  LayoutRoot is the root grid where all page content is placed  -->  
  17.     <Grid x:Name="LayoutRoot" Background="Transparent">  
  18.         <Grid.RowDefinitions>  
  19.             <RowDefinition Height="Auto" />  
  20.             <RowDefinition Height="*" />  
  21.         </Grid.RowDefinitions>  
  22.    
  23.         <!--  TitlePanel contains the name of the application and page title  -->  
  24.         <StackPanel x:Name="TitlePanel"  
  25.                     Grid.Row="0"  
  26.                     Margin="12,17,0,28">  
  27.             <TextBlock Margin="12,0"  
  28.                        Style="{StaticResource PhoneTextTitle2Style}"  
  29.                        Text="Cimbalino Sample" />  
  30.             <TextBlock Margin="9,-7,0,0"  
  31.                        Style="{StaticResource PhoneTextTitle2Style}"  
  32.                        Text="NavigationService" />  
  33.         </StackPanel>  
  34.    
  35.         <!--  ContentPanel - place additional content here  -->  
  36.         <Grid x:Name="ContentPanel"  
  37.               Grid.Row="1"  
  38.               Margin="12,0,12,0">  
  39.             <TextBlock>Page1 without parameter</TextBlock>  
  40.         </Grid>  
  41.     </Grid>  
  42.    
  43. </phone:PhoneApplicationPage>  
Page2.xaml is shown below. This page sets Page2ViewModel as the DataContext. This allows us to bind to the Parameter properly in the model in order to display the string that was sent from the MainViewModel.
  1. <phone:PhoneApplicationPage x:Class="CimbalinoSample.Page2"  
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  
  7.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"  
  8.                             DataContext="{Binding Page2ViewModel,  
  9.                                                   Source={StaticResource Locator}}"  
  10.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"  
  11.                             FontSize="{StaticResource PhoneFontSizeNormal}"  
  12.                             Foreground="{StaticResource PhoneForegroundBrush}"  
  13.                             Orientation="Portrait"  
  14.                             SupportedOrientations="Portrait"  
  15.                             shell:SystemTray.IsVisible="True"  
  16.                             mc:Ignorable="d">  
  17.    
  18.     <!--  LayoutRoot is the root grid where all page content is placed  -->  
  19.     <Grid x:Name="LayoutRoot" Background="Transparent">  
  20.         <Grid.RowDefinitions>  
  21.             <RowDefinition Height="Auto" />  
  22.             <RowDefinition Height="*" />  
  23.         </Grid.RowDefinitions>  
  24.    
  25.         <!--  TitlePanel contains the name of the application and page title  -->  
  26.         <StackPanel x:Name="TitlePanel"  
  27.                     Grid.Row="0"  
  28.                     Margin="12,17,0,28">  
  29.             <TextBlock Margin="12,0"  
  30.                        Style="{StaticResource PhoneTextTitle2Style}"  
  31.                        Text="Cimbalino Sample" />  
  32.             <TextBlock Margin="9,-7,0,0"  
  33.                        Style="{StaticResource PhoneTextTitle2Style}"  
  34.                        Text="NavigationService" />  
  35.         </StackPanel>  
  36.    
  37.         <!--  ContentPanel - place additional content here  -->  
  38.         <Grid x:Name="ContentPanel"  
  39.               Grid.Row="1"  
  40.               Margin="12,0,12,0">  
  41.             <TextBlock>  
  42.                 Page2 with parameter<Run Text="{Binding Parameter}" />  
  43.             </TextBlock>  
  44.             <Button Content="Go back" IsEnabled="{Binding CanGoBack}" Command="{Binding GoBackCommand}" Margin="0,66,0,0"/>  
  45.         </Grid>  
  46.     </Grid>  
  47.    
  48. </phone:PhoneApplicationPage>  

Up Next
    Ebook Download
    View all
    Learn
    View all