With the Windows 8 preview release earlier this week, developers are now faced with a whole new and exciting Microsoft stack. The Windows 8 architecture has something of a split-personality, incorporating a completely new runtime, WinRT together with the older Win32 and .NET framework. However, these sit on different sides of a physical divide in both the architecture and the user interface. For more details of this, see my earlier article.
The new WinRT APIs support both C# and XAML, having an interface that is very similar to its .NET counterparts. However, there are a number of differences, most importantly much of the UI now resides in a new namespace. It is clear that transitioning from Silverlight, WP7 or WPF development to using WinRT will be quite easy.
I am sure there exists classes of application that sit best in the Win8 Metro UI, for which you will use WinRT for development. There will also be classes of application that sit best in the Win8 classic desktop, for which you will still be using WPF and Silverlight to develop.
However ... there will certainly exist a class of application that sits well in both the Metro and Desktop environment. In the Win8 preview IE does just this.
This introduces a problem, how can we share code between our Silverlight Desktop and WinRT Metro applications?
I have previously presented talks and written articles on cross-platform application development. So I thought I would grab myself a copy of the Win8 preview release and see how easy it is to code-share between a Silverlight and WinRT Metro application.
This blog post describes a simple TwitterSearch application, the Silverlight version is shown below. Simply type in a search string to see the results retrieved from twitter:
A screenshot of the TwitterSearch application built for WinRT Metro is shown below:
When code-sharing between WPF, Silverlight and WP7 applications separation of concerns and solid design patterns are essential in order to navigate the framework differences. For that reason I use the Model-View-ViewModel pattern, this makes it easy to specialise the view for each platform, where they typically differ the most. I will use this same approach for WinRT.
The code is shared between the Silverlight and Win8 Metro application by having two separate solutions which both share files via the Visual Studio file linking feature.
The TwitterSearchViewModel which backs this application simply exposes a search string property and a list of tweets:
The IMarshalInvoke interface allows the view model to perform asynchronous calls via the Dispatcher, without being dependant on this UI class, more on this later.
It is here that I hit the first problem, WinRT has ICommand, but it lives in a different namespace! Time to add a WinRT compilation symbol to my WinRT project and throw in a pre-compiler directive:
Now my view model compiles just fine. However, when I hooked it up with the view, my bindings were only working in one direction. After appealing to Twitter, the MSDN forums and the WPF Disciples, Laurent Bugnion kindly informed me that WinRT has two different INotifyPropertyChanged interfaces. One within System.ComponentModel and the other in Windows.UI.Xaml.Data, if you use the one from System.ComponentModel it is ignored by the WinRT binding framework. Very confusing!
Fixing this is simply a matter of adding more platform specific namespaces:
My original code used WebClient, which is not present in WinRT. Fortunately HttpWebRequest is present in both, so I changed my code to use that, hence the need for the IMarshalInvoke interface to marshal execution back onto the UI thread.
As a result, much of the core logic, which makes use of Linq-to-XML, in the view model is shared between both applications:
This makes me happy :-)
On a side note, whilst WinRT does not have WebClient, it actually has something much better via classes such as SyndicationFeed which make use of the new C# async and await pattern for dealing with asynchrony. Of course, using these new APIs reduces the amount of code you share with the Silverlight .NET code.
The DelegateCommand implementation again hits the same problem of the same interface being located in a different namespace, yet despite this, most of the code is shared:
Despite the various XAML UI controls being in a different C# namespace, they use the same URIs for their XML namespace mappings. This makes it possible to share XAML as well as C# code between your applications.
However, in much the same way as it makes little sense to share XAML between WP7 and Silverlight due to differences in form-factor and user-experience, I don't think it makes sense to share XAML between Silverlight and Metro WinRT. The primary focus of the Win8 Metro applications is the touch-first tablet form factor, hence you would expect it to be quite different from a desktop application.
The following is the XAML for my Metro UI application:
If you are a Silverlight developer you will notice that everything here is standard Silverlight, it is just wired-up to different classes via the XAML namespace mappings.
I did discover that the IValueConverter signature within WinRT is a bit different. Within this application, the value conversion logic is so simple it is hardly worth code-sharing, however, it would be a very simple exercise if you wished to do so.
Finally, I did hit against one further problem. With WinRT it seems that there is a currently a bug which prevents ItemsControl binding to collections via INotifyCollectionChanged from working. This has been raised in the MSDN forums and I am sure it will be fixed. As a simple workaround I added the following code-behind (gasp!):
Creating a cross-platform WinRT / Silverlight application is entirely possible, using the same techniques that we currently employ for cross-platform Silverlight / WPF / WP7 applications. There are further complications relating to classes living in different namespaces and there will of course be other detail-level differences that this simple example does not touch upon. However, I think this presents a feasible and promising route for re-using existing Silverlight/ WPF code, and for developing applications that target the Win8 tablet, WP7 phone and Silverlight (or WPF) desktop with a single code-base.