1. Windows Store apps made easy with Prism and Prism project templates
2. Views, ViewModels and navigation

Previously described application is unrealistically simple. In reality, your apps will include more than one page and you will need some navigation mechanism to help users to browse between these pages.

Adding new pages

In addition to the project templates, Prism extension provides several item templates – Page View, View Model, Model and others.

Extensions and Updates

Use “Add New Item” dialog to add new Page View and View Model to Views and ViewModels folders correspondingly. Name them DetailsPage and DetailsPageViewModel.

Extensions and Updates

Next step is to set new DetailsPageViewModel as a data context for the DetailsPage. You can setup context manually, but Prism provides a handy ViewModelLocator class to do it semi-automatically. Why not fully automatically? Because you still need to setup ViewModelLocator.AutoWireViewModel property for DetailsPage.


<prism:VisualStateAwarePage 
    x:Name="pageRoot"
    x:Class="PrismApp.ViewModels.DetailsPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PrismApp.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:prism="using:Microsoft.Practices.Prism.StoreApps"
    mc:Ignorable="d"
    prism:ViewModelLocator.AutoWireViewModel="True">
    
    ...

</prism:VisualStateAwarePage>

How it works

For wiring Pages with ViewModels Prism framework uses a convention over configuration approach. Class names as well as Views and ViewModels folders are parts of this convention.

By setting AutoWireViewModel for DetailsPage to true we instruct ViewModelLocator to search DetailsPageViewModel in ViewModels folder. If such class is found, Prism will construct it and use as a data context for the DetailsPage.

Sounds logical, but let us look at the DetailsPageViewModel code.


using Microsoft.Practices.Prism.StoreApps;
using Microsoft.Practices.Prism.StoreApps.Interfaces;

namespace PrismApp.ViewModels
{
    public class DetailsPageViewModel : ViewModel
    {
        private INavigationService _navigationService;

        public DetailsPageViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
        }
    }
}

The class does not have default parameterless constructor, will Prism be able to construct the object? Actually no: if you will try to run the code as it is, ViewModelLocator will throw an exception telling us that an appropriate constructor was not found.

As you may expect, there is a way to instruct Prism which constructor to use. We can override App. OnInitialize method and properly configure ViewModelLocator.


using Microsoft.Practices.Prism.StoreApps;
using PrismApp.ViewModels;
using PrismApp.Views;
using Windows.ApplicationModel.Activation;

namespace PrismApp
{
    sealed partial class App : MvvmAppBase
    {
        public App()
        {
            InitializeComponent();
        }

        protected override void OnLaunchApplication(LaunchActivatedEventArgs args)
        {
            NavigationService.Navigate("Main", null);
        }

        protected override void OnInitialize(IActivatedEventArgs args)
        {
            ViewModelLocator.Register(typeof(MainPage).ToString(), 
                                      () => new MainPageViewModel(NavigationService));
            ViewModelLocator.Register(typeof(DetailsPage).ToString(), 
                                      () => new DetailsPageViewModel(NavigationService));
        }
    }
}

Navigation

With the object provided in constructor and implementing INavigationService interface, navigation is easy.


using Microsoft.Practices.Prism.StoreApps;
using Microsoft.Practices.Prism.StoreApps.Interfaces;

namespace PrismApp.ViewModels
{
    public class MainPageViewModel : ViewModel
    {
        private INavigationService _navigationService;

        public MainPageViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
        }

        public void GoToDetails()
        {
            _navigationService.Navigate("Details", null);
        }

        ...
    }
}

Navigation service use the same Views/ViewModels convention as ViewModelLocator. First parameter in Navigate() function defines target page name, service constructs full class name by adding “Page” suffix. Second parameter allows you to pass some data to the next page.

This concludes Prism Views and ViewModels discussion. Next post will talk about additional configuration techniques.

blog comments powered by Disqus