2012

Volume 27

Silverlight and WPF - Writing Silverlight and WPF Apps with Windows Runtime XAML in Mind

By Pete Brown | 2012

Windows Runtime (WinRT) XAML for new Windows Store apps is the latest member of the XAML and C#/Visual Basic family many of us have come to love. It all officially started in 2006 with the Microsoft .NET Framework 3.0 and “Avalon” (later named Windows Presentation Foundation, or WPF). After that came several more revisions of WPF, including the latest, WPF 4.5, and alongside we’ve had seven named versions of Silverlight (including 1.1 and 5.1), several versions of Windows Phone and more. You’ll even find part of the XAML stack available on .NET Micro Framework devices.

You might wonder why there are so many variations on XAML and the .NET Framework. Although many of the implementations have converged on similar uses (Silverlight to write desktop apps, for example), each platform was developed and optimized for different scenarios and target platforms. For example, Silverlight was designed to be cross-platform and Web-hosted. XAML on Windows Phone was designed for phone-specific scenarios and hardware, and WinRT XAML on Windows 8 was designed for high-performance, on the metal (x86/x64 and ARM), touch-first (but not touch-only) Windows Store apps.

Nevertheless, these implementations of XAML have far more in common than not. It’s because of these similarities that the differences seem so pronounced. Of course, tiny differences can cause a lot of development challenges, something I know from personal experience and from talking with other developers. However, the fact that we can even talk about compatibility at a detail level illustrates the similarity between the languages, libraries and markup.

In this article, I’m targeting two important scenarios: sharing code with a companion app and future-proofing your current development.

Companion App This is a simultaneous code-sharing, or cross-compilation, scenario for WPF and Silverlight application developers who want to develop companion Windows Store apps for Windows 8 at the same time.

Future Proofing In this scenario, developers are creating new WPF and Silverlight applications today but are not currently targeting Windows 8. When the organization adopts Windows 8, the developers want to be ready; they want to help ensure that appropriate portions of their apps will be more easily ported to the new Windows UI.

Decades of programming experience have taught us that reuse and portability are never free. However, with the techniques covered here, you’ll find much of the effort a minimal increment over what you would normally do to create well-architected apps.

Thoughtful Architecture Is Essential

Breaking large applications into smaller apps is possible only if you have good architecture to begin with. In fact, if your application has a lot of interdependencies between code modules, a lot of heavy class hierarchies, or otherwise feels like a ball of mud or throwaway code, reusing or porting anything will be extremely difficult. But don’t despair! Code can be refactored, and new code can be written with the new architecture in mind.

When designing new apps, I encourage XAML developers to follow a few key approaches: binding, the Model-View-ViewModel (MVVM) pattern and service classes.

BindingThe more you embrace data binding when developing in XAML, the easier it is to keep your logic separated from the UI. Ideally, you set the DataContext for the UI, and everything else is handled by binding with data or commands. In practice, few apps are able to attain this level of separation, but the closer you get, the easier your life will be.

The MVVM Pattern The MVVM pattern goes hand-in-hand with data binding. The ViewModel is what the UI will bind to. There’s a ton of great information (and toolkits, which I’ll cover later) available for free on the Internet and in books, so I won’t rehash that here.

Service Classes This approach is not to be confused with Web services. Instead, these are classes that provide reusable functionality on the client. In some cases, they might call out to RESTful or other services. In other cases, they might interface with your business logic. In all cases, they encapsulate potentially volatile code and make swapping out implementations easier. For example, in Figure 1, the ViewModel talks to service classes in order to use both platform services and to resolve external dependencies.

Relationship Between the ViewModel and Service Classes
Figure 1 Relationship Between the ViewModel and Service Classes

I know. You’re thinking, “Ugh! Another layer diagram.” But you know how important these concepts are. The intent is to decouple yourself from the platform you’re on as much as is reasonable within your budget and time constraints. By factoring out code that, for example, makes COM or p-invoke calls into desktop elements such as Windows Imaging or DirectShow, you can more easily replace that implementation with the WinRT camera API in your Windows Store app. Service classes are also a great place to encapsulate other platform differences, such as contract implementations: sending an e-mail from your Windows Store app would use a contract, but on the desktop it would likely mean automating Outlook or hooking into an SMTP server.

Of course, it’s easy to go overboard with architecture and never actually deliver. Good architecture should make development easier, not harder. If you find your team struggling with the minutiae of a particular architectural pattern, you’re probably wasting time. Instead, understand the patterns and what they bring, and then make intelligent and informed decisions about the trade-offs. In most cases, implementing 85 percent of a great architecture is better than 0 percent of the same. Similarly, the cost involved in getting that last 15 percent implemented is often not worth it.

Once you separate out platform-dependent code, quite a bit of other nontrivial code can be reused.

Embrace the New Windows UI Design Aesthetic

When developers first consider building Windows Store versions of existing Windows Presentation Foundation (WPF) and Silverlight apps, they immediately run into the roadblock of having to rethink the UX and visual design. To most developers, the prospect of restyling an entire application isn’t appealing. If you think Windows Store apps are in your future, a little work now to embrace the new Windows UI design aesthetic and guidelines will really pay off later.

The new Windows UI design provides a framework you can use to help guide your UI design choices. Several BUILD 2011 videos cover Windows Store app design. You can find them on MSDN Channel 9 at bit.ly/oB56Vf. In addition, here are a few things you’ll want to do to embrace the new Windows UI design aesthetic in your desktop apps:

  • Be authentically digital. Generally, shy away from the practice of designing the UI to be a fake analog of physical objects (skeuomorphism). You should avoid not only recreating physical objects, but also derived techniques such as glossy buttons, 3D shading, realistic shadows and glass backgrounds.
  • Have a clear type hierarchy. Don’t use a ton of different fonts, and for the fonts you do use, stick to a few key and easily distinguished sizes. Headings should be easily distinguished from field labels and help text.
  • Brand the application. Use your colors, logos, type and more as appropriate. It helps to have your Web developers and designers involved here, as they often have more hands-on experience with branding.
  • Use a page-based navigation metaphor. Silverlight developers will find this natural (the navigation framework is almost identical), but WPF developers might have a little more work to do to move from the traditional multi-window and dialog desktop approach.
  • Be task-focused. Keep the UI task-focused, and try not to cram every last thing on a single form. Unfortunately, users often think they want every function on a single page, but over time that becomes difficult to use, difficult to maintain and difficult to learn. In some cases, consider breaking large applications into smaller, task-focused apps.
  • Avoid unnecessary decoration. Keep the UI simple. You want to draw the user’s eyes to the work he needs to focus on, not to menus, navigation elements, window borders and other chrome.

Think of these concepts much like you would the older Windows UI design guidelines. They are guidelines you should follow if you want your app to feel familiar to the user and fit in with the new Windows UI. There’s more to it, of course, so I encourage you to look at the BUILD videos and to study examples of apps that other developers and designers have written.

One way to get a head start on using the UI styles is to copy the Windows Store app style resources into your own desktop apps. You can find many of the style resources in the Windows Kits folder. On my machine, that folder is located at C:\Program Files (x86)\Windows Kits\8.0\Include\winrt\xaml\design.

Some of the styles and resources are usable as is. Some will be unusable because of newer controls (ListView and GridView, for example), and some may require a fair bit of tweaking. However, this is a great way to get a modern look and feel for your app and to promote an easy transition between desktop and Windows Store styles. Even when you can’t use a style or template directly, you can learn from it to get a head start on your own styling work.

Your UI will still need some work when you move it to the Windows Runtime, but if you embrace these concepts in your apps now, you’ll go a long way toward ensuring that your transitions between the new Windows Store UI and desktop apps are not jarring to your users or your developers.

I’m all for less work. Style the app once, make the transition easier and get a modern look as a bonus.

Reusing Code and Components

The Windows Runtime gets a lot of attention in new Windows Store apps. It’s new, it’s fast and it has a lot of cool features. However, sometimes we forget that the Windows Runtime isn’t the sum total of what you have to work with; Windows Store apps built with XAML use a lot of the .NET Framework 4.5 along with the Windows Runtime. In fact, the .NET Framework 4.5 has significant updates, including many that enable it to be used side-by-side with the Windows Runtime. It’s still .NET, though—sharing source code, and even compiled binaries, with other .NET implementations is quite reasonable to do.

When sharing code with WPF apps, the best thing you can do right now is write your WPF code to work with the .NET Framework 4.5. Windows Store apps use a safe subset of .NET 4.5 alongside the Windows Runtime. When the .NET Framework provides the same functionality as the Windows Runtime (XAML is a great example), the .NET profile for Windows Store apps uses the WinRT version. If you stick to this subset as much as possible, your code will be extremely portable. You’ll find this especially helpful when you’re working with services and asynchronous code.

When sharing with Silverlight, you’re a little more restricted in that Silverlight doesn’t use the .NET Framework 4.5 or, for the most part, the Task Parallel Library. However, with the async targeting pack for Silverlight 5, Visual Studio 2012 users writing Silverlight applications gain access to some of the Task and async/await functionality. The Add Service Reference code won’t generate asynchronous client-side code, however. If that’s important to you, you can port the generated proxy code to Silverlight. A better approach, using the architecture I proposed here, is to encapsulate the Web service interactions inside local service classes.

What about code that’s identical? Model classes—and, in many cases, ViewModel classes—fall into this category. Here, you have two choices: Portable Class Library (PCL) projects and linked projects.

PCL Projects PCL is a great way to share compiled DLLs between different .NET targets. PCL enables you to share assemblies between .NET, .NET for Windows Store apps, Silverlight, Windows Phone and more. To use PCL, you need to restrict the assembly’s references to those on the compatibility list. Find out more about PCL at bit.ly/z2r3eM.

Linked Projects with Shared Source Code and Conditional Compilation This is a Visual Studio feature that enables you to have multiple projects, each targeting different platforms but with a single shared copy of the source code. In the past, I used this approach primarily when sharing code between ASP.NET on the server and Silverlight on the client. You can find an example on my blog at bit.ly/RtLhe7

Although I’ve traditionally used linked projects for most of my reuse scenarios, PCL has really grown up in recent versions. If you’re targeting WPF and WinRT XAML, PCL will let you use almost everything in the .NET 4.5 profile for Windows Store apps. When in doubt, start with PCL.

One thing I do like about the linked project approach is that I can provide platform-specific additional functionality through partial classes and conditional compilation. Conditional compilation symbols are set on the Build tab of the project properties page, as shown in Figure 2.

Project Properties Page Showing Compilation Symbols
Figure 2 Project Properties Page Showing Compilation Symbols

By default, a number of conditional compilation symbols are defined for you, as shown in Figure 3.

Figure 3 Conditional Compilation Symbols

Platform Compilation Symbol
Windows Runtime + .NET Framework NETFX_CORE
WPF/.NET Framework 4.5 Desktop (none)
Silverlight SILVERLIGHT

Note that the full .NET Framework doesn’t define any compilation symbols—it’s considered the default platform. If that makes you uneasy, you can add your own compilation symbols; just make sure you do that for all .NET Framework projects in your solution.

Conditional compilation is also how, in code, you can pull in different namespaces, depending on the target platform:

#if NETFX_CORE
using Windows.UI.Xaml;
#else
using System.Windows.Xaml;
#endif

In any nontrivial app, you’ll likely find yourself using both PCL and linked projects for sharing code. Sharing XAML, however, is more complex.

Sharing XAML UIs and Resources

For several reasons, sharing XAML is more difficult than sharing code. The most important step for doing so is to tailor the UI for the form factor and platform you’re targeting. (See “Embrace the New Windows UI Design Aesthetic” for some pointers here.) In most cases, your development time is better spent making sure the code is reusable, because you’ll see more payoff for less effort. Nevertheless, there will be both a desire and a tendency to share XAML across projects.

XAML doesn’t have the concept of conditional compilation. As a result, namespace differences are more difficult to manage than in code. In addition to the namespaces themselves, the way you import them into XAML has changed between WinRT XAML and the other versions.

Consider this .NET Framework XAML:

xmlns:localControls="clr-namespace:WpfApp.Controls"

And this WinRT XAML:

xmlns:localControls="using:WindowsApp.Controls"

Instead of the “clr-namespace” statement, WinRT XAML uses the “using” statement in XAML when importing namespaces. Why did the product teams do this? Imported namespaces in XAML might come from non-CLR code—C++, for example. Not only do you now have XAML support in C++, but you can write extension assemblies in C++ and use them in your .NET code. That means that the term “clr-namespace” is no longer accurate.

One way to deal with the differences is to dynamically load the XAML. Back in the Silverlight 1.1 alpha days, this was the way usercontrols were generated: the XAML was dynamically loaded and processed at run time. Since then, this approach has been used by app developers for flexibility across all platforms.

When you dynamically load XAML you’re working with strings. That means you can replace or subset text at will before loading it into the visual tree. For example, let’s say you have an empty usercontrol definition in your WPF or Silverlight project. The usercontrol is just a shell that defines namespaces and the class. Then you have an equivalent shell in the WinRT XAML project.

Here’s the .NET XAML:

<UserControl x:Class="WpfApp.Controls.AddressControl"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
  </Grid>
</UserControl>

And here’s the WinRT XAML:

<UserControl x:Class="WindowsApp.AddressControl"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
  </Grid>
</UserControl>

The two XAML user controls are plain-old-vanilla template output. The only change I made was to give the root Grid element a name and remove some unused namespaces to keep the code short. The codebehind for the controls can be shared using the code-sharing techniques, although I recommend partitioning the code into a separate shared class whenever possible.

Then, to load the XAML at run time, you can use code similar to what you see in Figure 4.

Figure 4 Code for Dynamically Loading XAML

public partial class AddressControl : UserControl
{
  public AddressControl()
  {
    InitializeComponent();
    LoadXaml();
  }
  private void LoadXaml()
  {
    string xaml =
    "<Grid xmlns=\"https://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
      "xmlns:x=\"https://schemas.microsoft.com/winfx/2006/xaml\">" +
      "<Grid.RowDefinitions>" +
        "<RowDefinition Height=\"Auto\" />" +
        "<RowDefinition Height=\"30\" />" +
      "</Grid.RowDefinitions>" +
      "<TextBlock Text=\"Address\" Grid.Row=\"0\" FontSize=\"10\" />" +
      "<TextBox x:Name=\"t1\" Grid.Row=\"1\" FontSize=\"15\" />" +
    "</Grid>";
    var reader = new StringReader(xaml);
    var xmlReader = XmlReader.Create(reader);           
    LayoutRoot.Children.Add((UIElement)XamlReader.Load(xmlReader));
  }
}

The code to load in WinRT XAML is even easier because of direct string loading support:

string xaml = "..."
LayoutRoot.Children.Add((UIElement)XamlReader.Load(xaml));

For simplicity, I loaded XAML from a hardcoded string here and used XAML that’s already portable and didn’t require any string manipulation. On the former, if you want designer support, make the code load text from a XAML resource file. Then, include all the usual class and xlmns definitions to support the designer, but throw them away during the XAML loading step.

Regardless of how the XAML gets into the visual tree, if you want to wire up events in the dynamically loaded XAML, you can do that from code as well:

LayoutRoot.Children.Add((UIElement)XamlReader.Load(xaml));
var t1 = FindName("t1") as TextBox;
if (t1 != null)
{
  t1.TextChanged += t1_TextChanged;
}

Just as you can load the XAML UI, you can also load resources at run time. You can create them from scratch or, using the same approaches shown here, load them from the XAML source:

private void LoadResources()
{
  string xaml =
    "<Style xmlns=\"https://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
      "TargetType=\"TextBox\">" +
      "<Setter Property=\"Margin\" Value=\"5\" />" +
    "</Style>";
  // Implicit styles use type for key
  var key = typeof(TextBox);
  App.Current.Resources.Add(key, XamlReader.Load(xaml));
}

When loading resources dynamically, be sure you have them loaded before they’re referenced. In the case of implicit styles, they simply won’t apply to anything already in the visual tree when the resource is created.

To be clear, this whole approach is a bit hacky, and it won’t work smoothly in every scenario. (At some point, the string manipulation can be more work than it’s worth.) But if you want maximum cross-platform reuse, this is one possible way to accomplish it. Personally, I’d use this only for critical UI components that are going to change a lot or are too complex or too numerous to simply copy and paste on a regular basis.

Of course, you could also write a custom build action or other Visual Studio extension to automatically handle the processing when files are saved, checked-out, built or for some other step.

The final way is to eschew XAML altogether and instead create your entire UI from code. Generally, I caution against this approach for most apps—it’s a lot of extra work, and you get zero designer support. However, data-driven UIs do extremely well with this approach. If you can create it in XAML, you can create it in code, as in the WinRT XAML shown in Figure 5.

Figure 5 Creating a UI with WinRT XAML

private void CreateControls()
{
  Grid g = new Grid();
  RowDefinition r1 = new RowDefinition();
  RowDefinition r2 = new RowDefinition();
  r1.Height = new GridLength(1, GridUnitType.Auto);
  r2.Height = new GridLength(30.0);
  g.RowDefinitions.Add(r1);
  g.RowDefinitions.Add(r2);
  TextBlock t = new TextBlock();
  t.Text = "Address";
  Grid.SetRow(t, 0);
  TextBox tb1 = new TextBox();
  Grid.SetRow(tb1, 1);
  g.Children.Add(t);
  g.Children.Add(tb1);
  LayoutRoot.Children.Add(g);
}

This code, with the exception of font settings (to keep the listing short), is equivalent to the dynamically loaded XAML that adds a TextBlock and TextBox to the LayoutRoot Grid, contained in a grid.

Consider Open Source Toolkits

Many of the best XAML/C# toolkits are open source. In an active open source project you’re likely to see interested people pick up and add the types of features that make moving between Silverlight, WPF and the Windows Runtime possible.

There are a number of MVVM toolkits, for example, which are mostly portable across the different flavors of XAML. By using one of these, you can help reduce the number of changes your source code needs when you’re sharing or porting it. Similarly, you’ll find controls, local databases and other toolkits available for use across platforms.

There’s always a risk that open source developers won’t work to target new versions of the platforms, but with access to the source code, you could fork the code and take that on should you want to. Just contribute the code back when you’re done.

Deciding What Should Be a Windows Store UI App

When it comes time to create your new Windows Store app, keep in mind that not all aspects of all desktop applications translate directly into Windows Store apps. For example, a large application with 300 forms, performing an entire suite of different functions for different users, is not necessarily a good candidate for the new Windows UI. Instead, Windows Store apps should be task-focused and tailored to a specific use.

Consider an insurance application. You might have one app that’s shared by a large number of users in the company. It handles supervisory functions for managing the security of users. It allows taking glass-damage claims over the phone, as well as on a laptop in the field. It has built-in functionality for creating new policies, and so on.

If you break up the application into a number of task-focused (or user-focused) smaller apps, it will be more appropriate for the new Windows UI. For example, you might want a separate field-adjuster app that’s focused specifically on taking down accident information at the scene. Because it’s focused, it includes support for taking photographs and recording video, as well as local caching of data for disconnected or poor-signal areas. This app probably shares a lot of code with the other apps in the enterprise, but its focus makes it easier to tailor to the scenarios for which it was built.

Wrapping Up

WinRT XAML, Silverlight and WPF have been created with different purposes in mind, but they’re more similar than different. Sharing code between them is easy, and sharing XAML is possible. There are lots of additional techniques you can follow to target all three platforms and move from the desktop to the new Windows Store UI. I’d love to continue this conversation on Twitter and on my blog at 10rem.net. If you’ve used other techniques for multi-targeting or porting code to the Windows Runtime, I’d love to hear from you.


Pete Brown is the Windows 8 XAML and gadget guy at Microsoft. He’s also the author of “Silverlight 5 in Action” (Manning Publications, 2012) and “Windows 8 XAML in Action” (Manning Publications, 2012). His blog and Web site are 10rem.net, and you can follow him on Twitter at twitter.com/pete_brown.

Thanks to the following technical expert for reviewing this article: Tim Heuer