Converting Windows Phone to Windows 8
Migrating a photo-sharing Windows Phone application to run under Windows 8.
- By Nick Randolph
Over the past two years, Microsoft has been heavily focused on promoting Windows Phone, and specifically encouraging developers to build applications using the Metro design language.
Metro came out of the work done to produce the core experience on Windows Phone, and is now widely used by developers writing applications for that platform. More recently we've seen the adoption of Metro across other devices and platforms, including Xbox and Windows 8.
While the look and feel of the platforms is very similar, the question remains as to how easily we can port our applications between them. In this article we're going to take a simple Windows Phone application and look at how it can be transformed into a Windows 8 application. We're going to focus on migrating the code, rather than the specific look and feel of the application.
The application we're going to work with is a simple Flickr viewer application. On startup it retrieves an XML feed of recent photos tagged with "wp7". The XML feed is converted into a collection of objects which are displayed in a ListBox.
The heavy lifting is all done in our MainPageViewModel class; it exposes a collection, FlickrImages, to which the ListBox is data bound. Listing 1 shows that we're using the WebClient class to download the XML feed as a string. This is then parsed into an XElement, allowing us to subsequently run a LINQ expression to extract a series of FlickrImage objects. These are subsequently added to the FlickrImages collection.
In order to display the FlickrImage objects, a ListBox is added to the MainPage with an appropriate ItemTemplate, as you can see in Listing 2. Points to note here are that an instance of the MainPageViewModel is created as a Resource on the page with key "ViewModel"; the "ViewModel" resources is then set as the DataContext for the page. The ItemsSource property on the ListBox is then data bound to the FlickrImages property on the current DataContext (which of course it inherits from the page, and is the instance of the MainPageViewModel class).
The only thing left to do is to call the Load method on the MainPageViewModel, which is done in the OnNavigatedTo method on the MainPage.
public partial class MainPage
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
(DataContext as MainPageViewModel).Load();
Running this sample will yield a basic application showing a list of photos and their corresponding titles from Flickr, as shown in Figure 1.
[Click on image for larger view.]
|Figure 1. A Windows Phone Flickr feed of photos.|
The next part is for us to convert this into a Windows 8 application. The first step is to copy our application across to our Windows 8 machine. Alternatively you can install the Windows Phone 7.1.1 Update on your Windows 8 machine so that you don't need to keep switching back and forth.
If you attempt to open your Windows Phone application in Visual Studio 11 (required for Metro application development for Windows 8), you'll find that the solution opens successfully but the Windows Phone project fails to load. This is because there isn't a version of the Windows Phone SDK that works in VS11.
The reality is that even if we could open the project, we'd still need to create a new Windows 8 Metro project, since there are substantial incompatibilities in the XAML and page model that mean that almost none of the UI is reusable. Thinking this through, you probably don't want to reuse a 480x800 layout for your slate/desktop application anyway.
Thus, the next step is to add a new project to your solution: Add New Project / Visual C# / Windows Metro style / Blank Application. We're going to call the project MetroFlickrImages.
We still want to reuse as much code as possible, so we're going to add a reference to the MainPageViewModel class into the new project. Right-click the project and select Add / Existing Item / locate MainPageViewModel.cs / Add as Link (the dropdown on adjacent to the Add button). As soon as you do this you'll notice build errors in your application, as a result of the differences between the Windows Phone and Windows 8 (WinRT) programming model.
Fixing this requires replacing the use of WebClient (not supported in WinRT) with the use of HttpWebRequest. In doing this, we'll also make a switch to using the new asynchronous programming model. This will clean up the code, without impeding the user interface of the application. The resulting code is shown in Listing 3.
Notice that instead of calling BeginGetResponse on the request object, typical for a Windows Phone application, we're calling GetResponseAsync. This method call is prefixed by the await keyword and the Load method is prefixed by the async keyword. This combination means that the Load method can be invoked from the UI thread and will execute in a seemingly sequential manner, but without blocking the UI thread while it makes the network call.
While the GetResponseAsync method initiates the network call to download the XML feed, the UI thread continues to execute. When the method call returns, the Load method continues to execute, back on the UI thread, to allow the XML to be processed in a sequential manner. This significantly tidies up the code and makes it much easier to follow the thread of execution, rather than having to jump between method calls and event handlers or callbacks.
The XAML in Listing 4 is used to create an instance of the MainPageViewModel class, wire it up as the DataContext for the page and then connect the FlickrImages property to the ItemsSource property on a ListBox.
Notice one slight difference in the way that Resources are wired up, both for the DataContext and the ItemTemplate for the ListBox. Instead of referencing the resources using the StaticResource element (as per the XAML for the Windows Phone application), the Metro application uses a Binding element with the Source attribute set to be the StaticResource. This is because there is currently no support for the StaticResourceExtension markup (despite Blend attempting to use it).
Running this code creates the Windows 8 application seen in Figure 2, running in the VS11 simulator.
[Click on image for larger view.]
|Figure 2. The completed Windows 8 application.|
The question now is whether we've broken anything in our Windows Phone application with the changes we made to MainPageViewModel.cs. If you don't have the Visual Studio Async CTP installed, you'll find that your Windows Phone application will no longer compile.
After installing the CTP, you'll need to add a reference to the AsyncCtpLibrary.dll. You need to use the Phone version of this .dll, which will be installed to %User%\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary_Phone.dll.
With the Async CTP installed and referenced, your Windows Phone application should again build. However, running the application will result in a NotSupportedException when it attempts to load the XML from the response stream. To fix this, simply set the AllowReadStreamBuffering property on the HttpWebRequest object to true.
var request = HttpWebRequest.CreateHttp("http://api.flickr.com/services/feeds/photos_public.gne?format=xml&tags=wp7");
request.AllowReadStreamBuffering = true;
var resp = await request.GetResponseAsync();
Here we've made the statement conditional, so that it's only set for the Windows Phone application. Now you have both the Windows 8 and Windows Phone applications sharing the same core logic, but they have their own project structure and page layouts.
In this post you've seen how to adapt a simple project to allow reuse a part of your application across both a Windows 8 and a Windows Phone project. As Microsoft gets closer to a release of Windows and looks to update the Windows Phone platform, we'll hopefully see better support for reusing code between the projects; but for now we have to put in extra work to prepare for the future.
Nick Randolph runs Built to Roam, a consulting company that specializes in training, mentoring and assisting other companies build mobile applications. With a heritage in rich client applications for both the desktop and a variety of mobile platforms, Nick currently presents, writes and educates on the Windows Phone platform.