Windows 8.1 Store Apps, Prism and Visual Studio Templates

In writing a post last week about the availability of the Prism framework (and guidance) for Windows 8.1 Store Apps, I talked a lot about how a blank app with Prism might compare with a blank app using the standard Visual Studio templates.

Whilst writing that article, I was thinking that it’d be “kind of nice” if the Prism guys shipped a template or two for Visual Studio to make that whole piece of work involved in “getting started” on a new app as easy as it is to just use the File->New Project option in Visual Studio.

The Prism team don’t ship templates themselves but they mentioned that Dave over here does have a set of templates and Dave also commented on my post and included a link to his post about the templates (thanks Dave!);

Prism Templates (on Dave’s blog)

I thought I’d download these from the Visual Studio Gallery and see what it was like to get started.

As Dave’s post explains, this adds two new project templates into Visual Studio;

image

and I thought I’d experiment with the “Prism App” template to compare using it with what I did in my previous blog post because, naturally, the other template brings in the whole topic of Inversion of Control and a specific IoC container (Unity) which may or may not be the direction that you want to go in.

Creating a new project means that I don’t need to go out and explicitly reference the Prism libraries because they are already present;

image

and looking at my App class, it’s already been derived from the Prism MvvmAppBase class and that class has just a little bit of code in it;

  sealed partial class App : MvvmAppBase
  {
    public App()
    {
      this.InitializeComponent();
    }

    protected override Task OnLaunchApplication(LaunchActivatedEventArgs args)
    {
      NavigationService.Navigate("Main", null);
      return Task.FromResult<object>(null);
    }

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

Much like I did in my previous post this just makes sure that when the app is launched it navigates to the “Main” page and the OnInitialize override says that the MainPage should be provided with an instance of the MainPageViewModel which is constructed with the INavigationService that is owned by the App.

In line with Prism’s convention, my “Main” page is a class called MainPage.xaml in a sub-namespace called Views and it’s already in the project;

image

and the template has done the right thing to ensure that this page is derived from Prism’s VisualStateAwarePage which means that the page picks up some abilities around determining visual state and also around navigation. The XAML that the template uses also specifies that the framework should automatically work out the right ViewModel to provide the DataContext to the page (done via the ViewModelLocator.AutoWireViewModel property).

The other thing that the page template does is to add in a little piece of XAML to define a page with a grid containing a header section and a content section. In the header section is a title and a “go back” button which is wired to the GoBackCommand that the VisualStateAwarePage provides.

<prism:VisualStateAwarePage
    x:Name="pageRoot"
    x:Class="PrismApp1.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PrismApp1.Views"
    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.Resources>
        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">MainPage</x:String>
    </prism:VisualStateAwarePage.Resources>

    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" 
                    AutomationProperties.Name="Back"
                    AutomationProperties.AutomationId="BackButton"
                    AutomationProperties.ItemType="Navigation Button"
				    Command="{Binding GoBackCommand, ElementName=pageRoot}"
					IsEnabled="{Binding CanGoBack, ElementName=pageRoot}"
				    Margin="39,59,39,0" 
                    Style="{StaticResource NavigationBackButtonNormalStyle}"
                    VerticalAlignment="Top" />
            <TextBlock x:Name="pageTitle" 
					   Grid.Column="1" 
                       IsHitTestVisible="false" 
					   Margin="0,0,30,40"
					   Style="{StaticResource HeaderTextBlockStyle}" 
			           Text="{StaticResource AppName}" 
					   TextWrapping="NoWrap" 
					   VerticalAlignment="Bottom" />
        </Grid>
    </Grid>
</prism:VisualStateAwarePage>

There’s no code in the code-behind for this page and then the template has also created that ViewModels folder and dropped a class called MainPageViewModel into it. That class looks like;

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

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

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

so there’s really nothing to that at the moment.

From that starting point, creating the same “Hello World” style app that I had in my previous post is trivial. I can simply add some data property onto that ViewModel;

  public class MainPageViewModel : ViewModel
  {
    private INavigationService _navigationService;

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

    public string ThePieceOfData
    {
      get
      {
        return (this._thePieceOfData);
      }
      set
      {
        base.SetProperty(ref this._thePieceOfData, value);
      }
    }
    string _thePieceOfData;
  }

and then I can bind to it from the UI;

    <Viewbox Grid.Row="1" MaxWidth="288">
      <TextBox Header="Enter Some Data"
               Text="{Binding ThePieceOfData,Mode=TwoWay}" />
    </Viewbox>

and if I wanted that piece of data to survive Windows’ suspend/terminate/re-launch cycle I can simply annotate it;

image

and that all works quite nicely and because this is a VisualStateAwarePage I can leave (or override) the base class implementation of DetermineVisualState which takes a width and height and returns a state name that can be used to change the UI into a particular visual state via the Visual State Manager. So, if I pop into Blend and define some really obvious UI changes for states called DefaultLayout, PortraitLayout, MinimalLayout as below;

image

then moving the UI into a portrait size drives that state transition as below;

image

In terms of the new item templates that David’s work installs – on the “Add Item” dialog in Visual Studio I get;

image

  • The Model item simply adds a class derived from ValidatableBindableBase which essentially overrides the SetProperty base class method to perform validation as property values change and collect them up in an Errors dictionary. The validation performed (all detailed in the docs) is based on the ValidationAttribute types from System.ComponentModel and the mechanism here to me feels very similar to that based around IDataErrorInfo/INotifyDataErrorInfo which I think came into Silverlight at version 4.
  • The Page View item adds another page to the project in the same way as the initial page is added to the project.
  • The View Model item adds another view model to the project in the same way as the initial view model is added to the project.
  • The Pub Sub Event item adds a class derived from Prism’s PubSubEvent<object> class for loosely coupled eventing – this is kind of a topic in its own right and I talked a bit about it here and the official docs on it are here.
  • The UserControl View item – I’m not so sure about. I couldn’t see a difference here between this item and a standard UserControl item template so I’d have to come back to this one.

I think these templates are a great helper for someone wanting to just get started with Windows Store apps – it’s clear where responsibility lies and there’s not tonnes of complex code in the projects but the framework has a tonne of flexibility for you to start to take control over how things are being done and altering some of the conventions as/when you feel comfortable with doing that.

For me, I’m going to have a think around whether I’d use these templates for demos in the future rather than just starting with Visual Studio’s blank projects – it feels like it would make life easier.