Windows 8 Store Apps - Lessons I've learned after publishing two apps

08 January 2013 (Updated 10 February 2013)

Summary:
In this post I briefly review some of the main lessons I've learned from having published two Windows 8 apps to the Windows Store.

Introduction

I've recently developed two apps which are now in the Windows Store:

  1. Class Browser Plus is a Windows 8 Developer's utility that enables you to view the properties, methods and events (along with help text) for all Windows 8 classes. You can browse all the classes, or view classes grouped by namespace (functional area). The Snippets feature allows you to browse simple, concrete examples of how to use key Windows 8 classes and features
  2. Visual Snippet Library allows you to open-up your Visual Studio code snippet library so you can quickly browse, search, view, edit and create snippets. Each snippet is represented as a tile, with a live-preview of the code. Every code language has a color-coded background, so you can see the most important snippet properties at a glance

I developed both apps as a learning exercise, because I wanted to experience the full Windows 8 application development lifecycle from design, coding and testing, through the certification and release process.

The overall points I'd note about the Windows 8 app development lifecycle are as follows.

Easy transition from WPF

As a long-time C# developer who is reasonably proficient with WPF/XAML, I found the transition to WinRT/C#/XAML to be pretty straightforward and painless. Everything worked as I hoped it would, and I could carry-forward most of my hard-earned WPF knowledge!

WinRT feels like .NET

Although the new WinRT framework is a little different from .NET, Microsoft have done a great job making the WinRT coding experience for .NET developers very smooth and instinctive. Unless you want to dig deeper, often you're not aware of when you're using the .NET framework or WinRT.

For example, WinRT has its own type system, but the Language Projection feature enables transparent calling into WinRT APIs from supported languages using language-native types and idioms. So, for managed app developers (C#/VB/XAML), this makes WinRT look and behave "like .NET", enabling you to pass (say) List<string>, even though WinRT actually requires its own equivalent type.

No System.Data namespace

By design, Windows 8 store apps can't install or access local databases, (although you can use embedded SQLite), or even use remote database servers. This (I assume) is all designed to enable Windows 8 store apps to install/uninstall quickly, easily, and without having numerous installation dependencies. There's also no access to the System.Data namespace, so if you were hoping to use a DataSet, DataTable, etc. in your app, you're out of luck! In practice, there are plenty of alternatives, including the wonderful Azure Mobile Services and embedded SQLite.

Use the Callisto framework

Tim Heuer (Microsoft) has developed a great open-source framework that assists the Windows 8 developer in a number of areas, including Flyouts and Settings panes. I extensively used the Flyout control in the Visual Snippet Library app:

There are two main ways of creating the content for the Flyout:

Dynamically create and add content

private void SimpleFlyout(object sender, TappedRoutedEventArgs e)
{
    var flyout = new Flyout();
    
    // Content for the flyout...
    var sp = new StackPanel();
    sp.Width = 400;
    sp.HorizontalAlignment = HorizontalAlignment.Center;
    sp.Children.Add(new TextBox { Text = "Hello", FontSize = 32 });
    sp.Children.Add(new TextBox { Text = "World", FontSize = 42 });

    flyout.Content = sp;  // Set the flyout's content

    // Place the flyout below the button that triggered it
    flyout.PlacementTarget = FlyoutBtn;
    flyout.Placement = PlacementMode.Bottom;  

    flyout.IsOpen = true;  // Open the flyout
}

Create a reusable User Control, and set that as the Flyout's content

private void FlyoutFromUserControl(object sender, TappedRoutedEventArgs e)
{
    var flyout = new Flyout();
    flyout.Content = new MyFlyoutUserControl();
    
    // Place the flyout below the button that triggered it
    flyout.PlacementTarget = FlyoutBtn2;
    flyout.Placement = PlacementMode.Bottom;

    flyout.IsOpen = true;  // Open the flyout
}

How did the Flyout close?

I frequently found myself in the situation where I wanted to know how the user dismissed the flyout. For example, did they escape out if it ("cancel"). The following code snippet shows how you can hook into flyout events to determine how it closed:

var flyout = new Flyout();
var flyoutCancelled = false;

flyout.Content = new MyFlyoutUserControl();
flyout.PlacementTarget = FlyoutBtn2;
flyout.Placement = PlacementMode.Bottom;

// Hook into the flyout KeyDown event
flyout.KeyDown += (o, args) =>
{
    if (args.Key == VirtualKey.Escape) flyoutCancelled = true;
    else if (args.Key == VirtualKey.Enter) flyout.IsOpen = false;
};

// Hook into the flyout Closed event
flyout.Closed += (o, o1) =>
{
    if (flyoutCancelled) return;  // User pressed Esc

    // Code to handle saving flyout data goes here...
};

flyout.IsOpen = true;  // Open the flyout

More Info on Callisto

For more info on Callisto, see the project's NuGet page (https://nuget.org/packages/Callisto).

You can install Callisto using Manage NuGet packages... in Visual Studio, or use the package manager console (Install-Package Callisto).

Consider using the MVVM Pattern

I didn't use the MVVM (Model-View-ViewModel) pattern with either of my Windows Store apps, but in retrospect I wish I had.

I was certainly aware of the benefits of MVVM, but was unsure if using it would introduce other complications. I've since discovered how beautifully MVVM works with Windows Store apps (data binding, commands, attached properties, etc.). My next Store app will definately be developed with the help of MVVM!

Get comfortable with the Async pattern

The async/await pattern is terrific, and it's everywhere in WinRT development. Definitely get comfortable with its use, and implement your own async methods whenever there's a chance a lengthy operation may be involved.

For example, I used the Repository pattern to manage reading/writing code snippets in the Visual Snippet Library app, and all the methods were implemented as async:

public async Task<CodeSnippet> GetSnippetAsync(string path)
{
    CodeSnippet snippet;

    try
    {
        // Get a file in the Document library by specifying a relative path
        var file = await StorageFile.GetFileFromPathAsync(path);

        // Read and parse the snippet's XML
        snippet = await ReadSnippetXmlAsync(file);
    }
    catch (Exception)
    {
        snippet = null;
    }

    return snippet;
}

Use the Windows App Certification Kit early in the dev cycle

This definitely falls into the "I wish I'd known this" category! I had essentially completed the development of the Visual Snippet Library app, built the app package using Visual Studio and then, as prompted, ran the App Certification Kit:

The report I got back stated that the app had passed with warnings:

Looking at the details of the warning, I experienced one of those slap-forehead moments:

The app had been configured to have access to the Documents library (so it could access the collection of Visual Studio code snippets). I vaguely remembered having read something about store apps not having access to the Documents library. However, I had looked at the app manifest Capabilities configuration, and there didn't seem to be an issue with adding access to the Documents library:

If ONLY I had clicked that little "more information" link I would have read sooner that the Documents Library capability is classed as a "special capability", and that (to quote the MSDN documentation on the subject):

"Apps that apply the special use capabilities require a company account to submit them to the Windows Store."

This was incredibly stupid on my part. I really should have checked more thoroughly. However, I was able to get around the limitation by having the app use local storage (i.e. in the "C:\Users\{username}\AppData\Local\Packages\{appname}\LocalState" folder).

Note that apps CAN still access the Documents library if the user grants permission to read/write through any of the picker mechanisms (FileOpenPicker, FileSavePicker, FolderPicker, etc.). They key idea here is that the user knowingly grants you permission by (say) selecting a folder in the Documents library. The picker returns a StorageFolder object, which you can then use to read a file, etc. What you can't do is try to programmatically create a StorageFolder object by supplying a path to the Documents Library - it'll throw an exception if you try

The certification process sometimes can be painful

The process of submitting your app for certification by Microsoft is actually pretty slick. There's a nice, easy-to-follow workflow on the dev centre store portal site. Once you have an account, submitting an app is very straightforward. However, with my first app, I made a mistake when supplying the URL for the app's associated web site. Somehow I managed to copy & paste the URL of the local (localhost) version of the site, rather than the actual production site. When, after seven days, I got the certification report back from Microsoft, I found that the test engineers stated that "the web site described in the app doesn't exist".

I was convinced the issue was that the link in the About screen was wrong - I checked it, it seemed to be OK and certainly "worked on my machine". I re-submitted and seven days later got an identical report. Eventually I realized the issue was in the app's certification form on the store portal (another slap-forehead moment!). Once that was fixed, I re-submitted again and this time the app passed and was added to the store.

The point is that a lot of frustration could have been prevented if the certification report had said "hey stupid, you put localhost in your app's support site URL on the store form"

Conclusion

In this post I reviewed some of the main lessons I've learned from having published two apps to the Windows Store. The main thing I've learned is that you really should run the Windows App Certification Kit early in the dev lifecycle. This way, you'll be alerted early-on to any potentially silly assumptions, errors and omissions!