Building an End-to-End Windows Store App – Part 1

In previousposts, I’ve alluded to one of our key focus areas for Visual Studio 2012 being the theme of connected devices and continuous services. This includes creating a top-notch set of tools in Visual Studio 2012 to both design and build amazing Windows apps and the services that back them.

With Windows 8 and Visual Studio 2012 released, I’ve decided to explore and document the end-to-end development of a basic Windows Store app that uses services on the backend. For this task I’ve chosen to use Visual Studio Express 2012 for Windows 8.

My primary goal here is to highlight just how straightforward it is now to build a modern, connected experience. For the sake of simplicity and minimizing the coding involved, I’ll build a simple RSS reader: “News by Soma.” In this two-part blog post, I’ll document the experience of building this app. Hopefully my notes are detailed enough that you can follow along and build (and then expand upon) your own version of this app, as well.

Getting Started

Since my goal here is to showcase the full end-to-end experience, I’m starting from a Windows 8 system without Visual Studio installed. I download the Visual Studio Express 2012 for Windows 8 installer, click through the setup wizard, and begin the installation:

Within a few minutes, I have my development environment up and running:

From File | New Project, I create a new Windows Store “Grid App (XAML)” using C#:

The Grid App template maps nicely to the scenario I have in mind, that of being able to have multiple RSS feeds (the “groups”), each of which contains multiple posts (the “items” in each group). The template provides all of the infrastructure necessary to build such an app very quickly. After the project is created, I press F5 to see my (not yet modified) app in action:

With the basic structure in place, I can now begin customizing it for my specific needs.

Configuring Basic App Properties

I of course want my app to look nice, so I spend a little time in Visual Studio customizing its properties via the Package.appxmanifest file. Opening this file presents a detailed editor in Visual Studio:

Here I configure both my app’s tile (for the Windows Start page) and splash screen (displayed when the app starts) the way I want them. This involves creating several images, which I do by starting with a picture of myself, and creating various cuts of it in Paint to fit the sizes specified in the configuration editor (e.g. 150×150 for the Logo, 310×150 for the Wide Logo, etc.):

This results in a nice tile experience when the app is pinned to my Start screen, whether using the Small tile:

or the Wide tile:

My app also now has a nice splash screen experience:

Getting Data

The Grid App template gets all of its data from a SampleDataSource type (in the file DataModel\SampleDataSource.cs) that exposes an AllGroups property which returns an ObservableCollection<SampleDataGroup>. This enables the UI to data bind to a collection of groups, each represented by the generic data model type SampleDataGroup. SampleDataGroup in turn contains a collection of SampleDataItem instances.

In my app, SampleDataGroup maps to RSS feeds, and SampleDataItem maps to the entries in a feed. Rather than replace SampleDataGroup and SampleDataItem with my own custom data types, for the sake of simplicity I simply repurpose them. The template includes on these types enough relevant properties so I don’t actually need to modify them at all; rather, I just need to modify SampleDataSource to populate and return instances of these with the right data.

There’s a fair amount of code in the SampleDataSource type included with the template, much of which is about populating the “lorem ipsum” nonsensical text items shown in the previous screenshots. I delete all of that, and replace the AllGroups property with a simple static declaration (fixing up all of the references in the process):

My UI can continue binding to AllGroups, which is initially empty. As new groups (RSS feeds) are added to AllGroups, the UI will be notified automatically of the addition and will update itself accordingly. Therefore, I need to expose a method to add groups:

Using the SyndicationClient class from Windows Runtime (WinRT), and the new async/await keywords in C#, I asynchronously download the feed at the requested URL. I then create a SampleDataGroup to represent the feed, populating it with information about the feed from the SyndicationFeed I was handed. And then for each item in the syndication feed, I map its properties into a new SampleDataItem. These items are all added to the group, and then the group is added to the AllGroups collection. With that, I’m almost done teaching the app how to get all of the data it needs.

The one remaining piece of code here has to do with images. The UI knows how to bind to SampleDataGroup and SampleDataItem, including showing an image for every group and item. Typically, RSS feed items aren’t associated with an image, but I want something appropriate and interesting to show up in the UI for each feed item whenever possible. As such, I have one more function that parses the RSS item looking for PNG and JPG images, returning the first one with a fully-qualified path it finds:

Finally, before I can really run the app, I need one more change: to modify the GroupedItemsPage.LoadState method (in the file GroupedItemsPage.xaml.cs) to use this new SampleDataSource.AddGroupForFeedAsync method. I replace the LoadState from the template with one line to hook up AllGroups to the UI, and add a few additional lines to initially populate the UI with a few blogs:

And that’s it. I’m now able to F5 again to see RSS data populated into my app:

Main grouped-items page:

Group page (when I click on a group header on the main page):

Item page (when I click on an item on the main or group pages):

One thing to note here is that I haven’t modified the default template for the item page yet, and it uses a RichTextBlock to display the post’s contents. As a result, the HTML from the RSS item is displayed as the HTML source rather than as rendered content.

To make this a bit nicer, I can update the template to render the HTML. The ItemDetailPage.xaml displays the SampleDataItem using a FlipView control, with a DataTemplate that uses a UserControl for the template item. I replace the contents of that UserControl (which in the original code contains the RichTextBlock-related controls) with the following XAML that uses a WebView control:

The WebView control itself doesn’t have a property that allows me to bind the WebView directly to the HTML string contentI already have, but I found code from Tim Heuer for an HtmlSource extension property that uses WebView’s NavigateToString method to achieve the same thing. And with that addition to my project, I now see the feed item rendered nicely in the app:

User Interaction

In the previous section on Getting Data, I simply hardcoded which feeds I wanted the app to display. However, I want to allow the user to enter such their own choices of feeds manually, so I’ll augment the template UI slightly to enable this user interaction.

One of the common design elements of a Windows Store app is an “app bar.” I’ll use an AppBar control to allow the user to enter a URL into a TextBox and click an Add button to get the feed included in the app. I drag an AppBar control from the Visual Studio Toolbox onto the designer for my GroupedItemsPage.xaml file:

I then move the resulting XAML into a Page.BottomAppBar element so that the app bar shows up at the bottom of my app:

(Note that AddAppBarButtonStyle, along with ~140 other styles for AppBar buttons, is defined in the StandardStyles.xaml file included in the Grid App template, but it’s commented out by default. I just uncomment it so that I can use it here.)

To complete the experience, I need to implement the btnAddFeed_Click method (in the GroupedItemsPage.xaml.cs file), wiring it up to the SampleDataSource.AddGroupForFeedAsync method I previously wrote (and, of course, removing the three lines I previously hardcoded in LoadState):

With that in place, when a user brings up the app bar, types in a URL, and clicks the Add button, the feed will be added, and for the duration of the add operation, the app will display the progress ring and prevent the user from adding additional feeds.

Enabling Live Tiles

Windows 8 provides multiple mechanisms for creating live tiles on the Start screen. For the purposes of my app, I want to update my live tile to list the current feeds in the app.

To do this, in GroupedItemPage.xaml.cs I create a function to generate the template XML expected by the TileUpdateManager, and I use a TileUpdater to push the visuals to the tile:

(For your own apps, the “App tiles and badges” Windows SDK Sample includes some helpful code for working with tiles.)

Then I modify GroupedItemsPage.LoadState to call this UpdateTile method after successfully adding a feed:

if (awaitSampleDataSource.AddGroupForFeedAsync(feed)){ UpdateTile();}

Now, after starting my app and adding my blog feed and Jason Zander’s blog feed, I can see this information available on my tile:

Enabling Search

Having integrated with live tiles, the next feature I want to integrate is Search. Windows 8 provides the Search charm that enables users to search relevant apps from anywhere in the system.

To start this, I right-click on my project in Visual Studio and select Add | New Item…, picking “Search Contract” as the item to be added:

This does a few things:

It updates my package manifest to declare Search:

It adds a new SearchResultsPage.xaml to my project.

It augments my App.xaml.cs with the necessary OnSearchActivated method override to correctly connect a Search request from the system with my new SearchResultsPage.xaml.

The added SearchResultsPage.xaml (and associated SearchResultsPage.xaml.cs) already contains most of the UI and logic necessary to make this scenario work. So as with the other templates we’ve seen Visual Studio create, I just need to plug in the logic specific to my application and its data.

The SearchResultsPage.xaml.cs file includes a simple view model type called Filter. This type is used by the template to represent a group of search results, such that a user can see and select from multiple categories of results to quickly narrow down their choices. To simplify coding a bit, I first modify this Filter to make it Filter<T> and add a Results property to it… that way, I can perform one search and populate all of the filters, such that as the user chooses different filter categories in the UI, I don’t have to keep re-searching:

Finally, the SearchResultsPage.xaml page contains two lines of XAML that should be deleted. The Grid App template already includes the application name in the App.xaml file, so we don’t need to also configure that here:

<!– TODO: Update the following string to be the name of your app –><x:Stringx:Key=”AppName”>App Name</x:String>

With that, search is functioning in my application:

As it stands, this will only search the feeds that have been loaded into the app when the app’s main page loads. That works great if the search is performed while the app is running. If, however, the app isn’t running, its main page won’t have executed, and groups won’t have populated. If I were to persist feed information, then if the app hadn’t been running when the search request arrived, I could update the search logic to first load the feeds that had been persisted.

What’s Next?

In this first of two posts, I’ve explored getting up and running with Visual Studio Express 2012 for Windows 8, and using it to build a basic app that integrates with live tiles and search. In my next post, I’ll focus on extending this application via multiple backend services. Stay tuned…

Thanks. I am looking forward to see the app store open for individuals, twiddling my thumbs ever since RTM was out. Can you share the timeline if possible? Sad not a single devcamp made it in Hong Kong, us developers did not get the love :).

Would love to see a tutorial that take The Grid Template (like this tutorial) but uses the MVVM class to store local data to an XML File. Show the ability to add, update, Delete records in the XML file.

Nope, Soma, I'm afraid I can't let you call "Metro" apps "Windows Store" apps. According to Sinofsky's //build/ keynote last year, Win32 apps can appear in the store. Sure, the tiles are just basically advertisements that lead a person to a website where they purchase the Win32 app, but they appear in the store. So "Windows Store" app is not a sufficient name to distinguish Metro apps from desktop apps.

Really nice post! But what I am missing is a little bit more diversity regarding design, not only using the standard templates. How do you want to learn more about the "right" Modern UI? Maybe this could be included in future posts. Thank you 🙂

@Stephen Here is what I would like to see Soma blog about, the END OF VISUAL STUDIO AND .NET along with that dreadful user interface and instead return to the Visual Studio 6.0 DNA and building on a foundation that worked. That would be far better then forcing developers into an overly bloated, expensive and ugly IDE with a weak language that serves as nothing but glue to call API wrapper libraries none of which work well together.

The VS team and managers has set development back 20 years.

Here is another good blog post Soma and the visual studio team resign from Microsoft and vow never to write development tools again.

There have been some developer camps that have already happened in the Hong Kong area and there is a hackathon planned in the near future there as well. Please contact neille@microsoft.com if you need specific information about developer events in your area on Win8.

@Matt: Good question. Those hardcoded feeds were just temporary; it's a bit hidden, but later in the post, the post states "To complete the experience, I need to implement the btnAddFeed_Click method (in the GroupedItemsPage.xaml.cs file), wiring it up to the SampleDataSource.AddGroupForFeedAsync method I previously wrote (and, of course, removing the three lines I previously hardcoded in LoadState):" So while LoadState might get called again, it'll end up just loading the same feeds that were already available rather than adding additional ones. I hope that helps.

I’m wondering however, how to load the collection only once on startup and not fire every time I return to the main page. Is there a page method available for this as it is not preferred in my app to click a button to load initial data?