Windows 8 and Prism: Migrating a Simple Example

In some of our recent Windows Phone events, I’ve been using an example “application” (i.e. it’s a demo, not a whole app) to try and talk about an approach to structure code such that a reasonable percentage of it is portable across both Windows 8 and Windows Phone 8 and with that portable code packaged into .NET portable class libraries.

The “application” is one that presents 3 simple screens allowing you to search for photos on the flickR photo service. Screen 1 looks like this;

image

and Screen 2 looks like this;

image

and Screen 3 looks like this;

image

with an AppBar menu which saves the picture in question into the user’s Picture Library;

image

I have both a Windows 8 and a Windows Phone 8 variant of this and the implementation of this “application” tries to follow the MVVM pattern and the “architecture” ends up looking something like this (my diagram from the talk);

image

With the idea being that the bits in blue are all pieces of implementation specific to Windows 8, the bits in green are all pieces of implementation specific to Windows Phone 8 and the bits in the middle in black are all defined in portable class libraries and are re-used (at the binary level) by both implementations.

The structure of the app  looks like this in Visual Studio;

image

I have 3 views for the SearchPage, SearchResultsPage and PhotoDetailsPage. I then have 2 services that are specific to Windows 8 – one to save a photo into the pictures library and another to abstract the specifics of a navigation service so as to make it available to my view models and also so as to have a simple, cross-platform abstraction of it.

I then have a fairly standard App class and some bits to set up an Autofac container which is then later used to resolve the implementations of the services that are abstracted by interfaces in my abstractions library.

I take a “manual” approach to instantiating view models and linking them up to be the DataContext of a view (which I’d ideally move away from although it can make for a more complex demo).

In my first portable class library I have;

image

4 view models (plus a base class) to support the 3 views of my app;

  1. SearchPageViewModel
  2. SearchResultsPageViewModel + SearchResultViewModel (the view model behind each item displayed in the GridView in the view)
  3. PhotoDetailsPageViewModel

I also have a simple Model class (FlickrSearchItem) which represents the data that I deserialize back from flickR and then I have some code that knows how to call flickR’s API to do a search, get the results back and give me back instances of my Model class in a list.

This code (via the portable HttpClient library) turned out to be portable so I don’t currently have it abstracted but it would perhaps be better if I did have an abstraction of it so that it can be injected into classes that have a dependency on it.

I also have an implementation of ICommand in this library in the SimpleCommand class and a base class for my view models called ViewModelBase which implements INotifyPropertyChanged for me.

In my second portable “abstractions” library project I have;

image

so it’s just a couple of interfaces that abstract what it “means” to be a navigation service and what it “means” to be a photo saving service and those interfaces are then implemented by specific services.

Now, in talking about these ideas in an in-person session I find that I have a slightly poor signal:noise ratio because I feel I need to introduce some or all of;

  1. MVVM.
  2. Commanding.
  3. Binding and INotifyPropertyChanged.
  4. Abstraction and “services”.
  5. Inversion of Control and Dependency Injection.

and, frankly, there are areas where it’d make it a lot easier to lean on a framework and allow it to do some of this lifting for me.

Given the recent release of Prism for Windows 8 Store apps, I thought I’d take my Windows 8 version of this “application” and see what it’s like to rebuild it on top of that framework to see how much better my signal:noise ratio gets. This is my attempt…

Putting the Pieces Back Together on top of Prism

I wanted to start from scratch so the first thing I did was to make a Windows 8 project using the “Blank” template and then I added from NuGet the “Prism.StoreApps” package and then copied across a bunch of imagery that I’d used in my previous app into the Assets folder and set up the manifest to make use of them (e.g. splash screens and so on).

In the interests of initial “simplicity” I decided I’d bundle everything into a single project in the first instance so I set up a few folders;

image

and then got rid of MainPage.xaml.

Having done that, I brought across my views and code from my other projects omitting some pieces that I knew that Prism already had for me (e.g. an implementation of ICommand and a base class for my view models).

I changed the base class of the App class from the Visual Studio template to be MvvmAppBase from Prism rather than the Application class. I also took away all of the boiler plate code from my App class as I wasn’t sure how much of it I now needed.

I then visited my view models, taking away my original ViewModelBase base class and replacing with the Prism ViewModel class. I also refactored my FlickrService code such that I built an interface which abstracted it and then made the one view model that needed to use it take a dependency (at construction time) on that interface rather than on the implementation itself.

The other thing that I’d baked into my View Models was a dependency on a navigation service that I’d built so I took that away and replaced it with a dependency on the INavigationService that Prism provides and I overrode the ViewModel.OnNavigatedTo method on the two of my view models that needed to pick up a parameter passed by navigation (previously, I’d made this a responsibility of my own navigation service).

Where I made use of the Prism navigation service, I simply made calls like this;

    void OnSearchCommand()
    {
      this._navigationService.Navigate("SearchResults", this.SearchTerm);
    }

with the idea being that “SearchResults” (albeit in a hard-coded string literal!) is an abstracted token being used to navigate to my SearchResultsPage page.

Also, I took away my own use of my own SimpleCommand class and replaced it with Prism’s DelegateCommand which looks reasonably similar anyway.

In terms of my views, I took away any code which was manually resolving view models and setting DataContext values (this should never really have been present but the app I’m moving is a demo) and I also changed the base class of my pages to Prism’s VisualStateAwarePage although that’s possibly academic for this particular code. Finally, I made sure that each view was declaratively (i.e. in its XAML) setting the Prism ViewModelLocator.AutoWireVIewModel property to true.

At this point, I felt I was getting pretty close to where I’d started but there’s a degree of “wiring together” that needed to be done in order that;

  1. I navigate to my first SearchPage view when the app starts up.
  2. Navigation using a string token such as “Search” is resolved correctly to a page like SearchPage
  3. Views are able to create View Models and View Models are able to resolve the services on which they’ve taken a dependency

Apart from that, I was trying to keep my App class as “free of superfluous code” as possible.

For point 1 above, I ended up overriding the OnLaunchApplication method;

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

so that felt pretty minimal and for point 2 I ended up overriding the GetPageType method – this was purely because the default implementation looks to expect to take a page token like “foo” and attempt to resolve it to a type called “fooPage” but it looks to expect the namespace of that “fooPage” class to be the one of the currently executing assembly. My views weren’t named that way so I overrode;

    protected override Type GetPageType(string pageToken)
    {
      // My views are called MvvmStart.Views.{0}Page whereas the
      // base class expects something different.
      // Naturally, we wouldn't want to hardcode this namespace
      // right here in the 'real world'.
      string baseName = "MvvmStart.Views.{0}Page";
      string typeName = string.Format(baseName, pageToken);
      Type type = Type.GetType(typeName);
      return (type);
    }

and then, finally, for point 3 above I introduced an Autofac container and overrode the OnInitialize method to set it up;

  protected override void OnInitialize(IActivatedEventArgs args)
    {
      base.OnInitialize(args);

      ContainerBuilder builder = new ContainerBuilder();

      builder.
        RegisterInstance<INavigationService>(this.NavigationService).
        As<INavigationService>();

      builder.RegisterType<FlickrService>().As<IFlickrService>();
      builder.RegisterType<PhotoSavingService>().As<IPhotoSavingService>();

      builder.RegisterType<SearchPageViewModel>().AsSelf();
      builder.RegisterType<SearchResultsPageViewModel>().AsSelf();
      builder.RegisterType<PhotoDetailsPageViewModel>().AsSelf();
      builder.RegisterType<SearchResultViewModel>().AsSelf();

      this._container = builder.Build();
    }

Now, I should point out that I’m no Autofac expert so feel free to critique but this is essentially registering the navigation service, flickR service, photo saving service and then my view models so that they can be created by the container with their dependencies on those services resolved.

I then overrode the Resolve() method to make use of this container;

    protected override object Resolve(Type type)
    {
      return (this._container.Resolve(type));
    }

and that was it. Running, “working” (i.e. seems to be working as I don’t have tests for this demo) code within around 90 minutes on a train ride home on a Saturday night Smile

One thing I’ll say that I was particularly pleased with was that my SearchResultsPageViewModel looks like this;

image

it has a collection of SearchResultViewModel that it needs to populate which means it has to know “how” to create a SearchResultViewModel from a container and have its dependencies resolved.

I was quite pleased with the way that Autofac handled this for me in that rather than having to take a dependency on some “container interface” I just had to take a dependency on a Func<SearchResultViewModel> and Autofac automatically injected it for me. That is, the SearchResultsPageViewModel constructor looks like;

    public SearchResultsPageViewModel(
      INavigationService navigationService,
      IFlickrService flickrService,
      Func<SearchResultViewModel> resultViewModelFactory)
    {
      this._navigationService = navigationService;
      this._flickrService = flickrService;
      this._resultViewModelFactory = resultViewModelFactory;
    }

which I found neat but, no doubt, you’ve seen that sort of thing a thousand times Smile

This code doesn’t represent best practise in any way, shape or form (go get the Prism code and have a look at their sample) but it feels wrong to end the post without including the source code that I’m talking about so that’s downloadable from here if you want it.

Next steps – get as much of this back into my portable class libraries so that I can still get re-use across Windows 8/Windows Phone 8. How will that work with Prism when Prism isn’t portable?….