Just the other week on Blaine’s blog there was the announcement that Prism for WinRT on Windows 8.1 had been released by the Patterns and Practices team.
I’ve talked a little about Prism for WinRT before ( here and here ).
While the Prism team talks about Prism being for “Windows Store business apps” I see it as having much broader appeal in that Prism provides a tonne of guidance around how to build a structured, high quality app along with libraries that help you in doing that and a reference implementation of a business-style app that you can examine and compare your own implementation to.
I think anyone building apps for Windows Store can gain from reading through the Prism documentation with its top level topics like;
- Designing UX
- Using MVVM
- Creating and Navigating Between Pages
- Using Touch
- Validating User Input
- Managing Application Data
- Handling Suspend/Resume/Activation
- Communicating Between Loosely Coupled Components
- Working With Tiles
- Implementing Search
- Performance
- Testing & Deploying
It’s a really good guide – it’s worth investing time in but…
Isn’t Prism and MVVM Just Too Hard ™ ?
I was at an internal event at Microsoft a couple of months ago and there was some casual chat around topics like “Model View ViewModel” and patterns in general for Windows Store apps and there were a few folks chatting on the topic and the general view seemed to be something like;
“it’s just Too Hard ™ for regular developers to pick up those kind of techniques, the barrier to entry is too high”.
But this didn’t seem right to me.
I don’t think picking up some pieces from a framework like Prism necessarily means you have to be some kind of rocket-scientist.
In fact, I think that for a “Hello World” style example the code that you need to get a Windows Store app off the ground with Prism is less than the code that ships in the blank templates.
I also think it’s simpler code and cleaner code.
Using that new version of Prism as an example, I thought I’d just illustrate how easy and clean it is to make “Hello World”.
In the past, I took the Visual Studio Grid template and re-wired it on top of Prism so that might be something to also take a look at.
The first thing to do is to make a blank project in Visual Studio.
With that made, spark up the “Manage NuGet Packages…” dialog off the solutions “References” section and add in the Prism libraries;
The next step is to change the base class of the app from Application to MvvmAppBase in both the App.xaml.cs file and in the App.xaml file. Here is my entire App.xaml.cs file at the end of that process;
namespace App7 { using Microsoft.Practices.Prism.StoreApps; using System.Threading.Tasks; using Windows.ApplicationModel.Activation; sealed partial class App : MvvmAppBase { public App() { this.InitializeComponent(); } protected override Task OnLaunchApplication( LaunchActivatedEventArgs args) { this.NavigationService.Navigate("Main", null); return (Task.FromResult<object>(null)); } } }
That’s less code than you would have in the standard App.xaml.cs file that is part of the blank template.
There’s no Suspending event handler, there’s no logic for whether to create a Frame or not. It’s very little code. The App.xaml needs to change as well;
<p:MvvmAppBase x:Class="App7.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:p="using:Microsoft.Practices.Prism.StoreApps" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App7"> </p:MvvmAppBase>
The one piece of code that I’ve really added to the app so far is a call to the NavigationService which tells it to navigate to a string “Main” suggesting that this is the “Main Page” for the app. There is a convention in Prism (which can be overridden) which by default will cause the framework in my app (App7) to look for a page type called App7.Views.MainPage.
The blank project already gives me a page called MainPage so it’s relatively easy to drop the 2 files (XAML and C#) that make up that page into a Views folder;
and that doesn’t cause Visual Studio to put the MainPage class into a Views namespace so it’s necessary to make a little change to the MainPage.xaml.cs file;
and the corresponding XAML file;
and that’s it. I’ve got a blank application up and running and it contains less code than the blank application template that ships with Visual Studio. It also contains fewer conceptual pieces. Here there are;
- An App.
- A Page.
- A Navigation Service.
whereas in the blank template you’d have all of these but at least some additional code which does something with;
- A Frame which also represents a navigation service for you and that can sometimes be a problem when you’d like to access the capabilities of a navigation service without having to pick up all the baggage of a Frame object.
- A Window.
- A Suspending event.
so it’s not a lot more but it is more to deal with just to get a blank page on the screen.
Adding Some Data
What if I wanted to edit a piece of data – a simple string to edit for example. It’s pretty easy to author some “UI” for that – I can edit my MainPage.xaml to add a TextBox;
this is pretty abstracted – there’s a piece of data somewhere called TheText and that’s all the UI cares about which is probably close to “as good as it gets” in terms of keeping the UI separated.
How do I feed that UI with data? By writing a ViewModel which provides the TheText value with change notification. This is pretty simple with Prism, I can create a ViewModels folder and a class within it called MainPageViewModel;
namespace App7.ViewModels { class MainPageViewModel : ViewModel { public string TheText { get { return (this._theText); } set { base.SetProperty(ref this._theText, value); } } string _theText; } }
and I need to tell the page that this is the ViewModel type that provides data for the page. This can be as simple as altering the XAML file;
and that’s it.
Now when I run the app, the framework will construct the MainPage and navigate some Frame (which we haven’t been exposed to) over to that page and it’ll also construct an instance of the MainPageViewModel (based on convention which can be rewired) and set that instance as the DataContext of that page for the binding to be resolved.
It’s easy. It’s logical. There’s an app, a view, a view model and they have as little knowledge of each other as possible.
What about handling something more complicated like the Suspend/Terminate Process Lifecycle Management that Windows Store apps have to deal with?
Surviving Suspend & Terminate
One of the joys (or pains ) of writing a Windows Store app is handling what happens when your application suspends and terminates. Even my one TextBox UI example is broken with respect to this functionality. For example, if I am running my “app” and I enter some text into the TextBox;
and I then use the highlighted “Suspend and Terminate” button to simulate the system shutting down the app before re-running the app then I see;
and so the app has lost its volatile state and the user might well consider the application broken if the time between the system terminating the app and the user re-running it was short enough that the user could remember what the app was supposed to be doing the last time they saw it.
Now, if you take a look at the Visual Studio templates you’ll know that there’s a few “moving parts” involved in saving state. It goes something like this;
A class called the SuspensionManager is linked into the Page via the NavigationHelper and that links into the Frame and when suspension occurs the Page code handles some OnNavigatedFrom event and it can save state into dictionaries which are provided by the NavigationHelper but which are owned by the SuspensionManager and which your App class then ultimately has to save to disk in its handler for the Suspending event by asking the SuspensionManager to do that saving for it.
Then…when your app runs back up it has to register the Frame with the SuspensionManaer and then it needs to see if the PreviousExecutionState was set to Terminated and, if so, the app has to ask the SuspensionManager to re-load the saved state.
For me, this often feels like I’m being exposed to more moving parts than I need to be and those parts aren’t necessarily in a position to be able to access the data that needs saving.
In a Prism app, this responsibility for persisting volatile state could be handled by the ViewModel.
Taking the code that I already have, I can fix the current suspend/terminate problem with my “app” by adding one attribute;
It’s easy. It’s logical. It’s not the only thing that I can do – I can take more explicit action if necessary but it’s easy to get going with.
Wrapping Up
Kicking off with a framework like Prism for Windows Store apps doesn’t have to be “hard”. Sure, there are lots of other things that you can do here to alter the convention and you can start to wire up an IoC container and so on but getting started is pretty simple and, arguably, leaves you with less code in a blank(ish) project than you would have if you just started with the built-in templates.
It might be worth giving those Prism docs and libraries a look if you’ve been there before and got the impression that there’s some big barrier to entry.