Sunday, November 13, 2011

Sharing .xaml in WPF and Silverlight

Sharing code between WPF and Silverlight is not difficult. Good how-to is in the Prism guide. However sharing more complex .xaml is not so easy. You have to handle different namespaces and properties.

Handling different namespaces

Silverlight toolkit components are accessible via special namespace. So if you want to use a WrapPanel in Silverlight, you write something like this:

<UserControl x:Class="UnifiedXaml.TestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
    <toolkit:WrapPanel></toolkit:WrapPanel>
</UserControl>

WPF world is easier:

<UserControl x:Class="UnifiedXaml.TestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <WrapPanel></WrapPanel>
</UserControl>

It's clear those two .xaml files are so similar that they should be just one file. Here is one tiny line that makes it possible:

namespace UnifiedXaml
{
    public class MyWrapPanel: WrapPanel { }
}

From now on, you can share the .xaml file:

<UserControl x:Class="UnifiedXaml.TestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:ux="clr-namespace:UnifiedXaml">
    <ux:MyWrapPanel></ux:MyWrapPanel>
</UserControl>

Handling different properties

When you follow Prism guidelines, you have separate projects for WPF and Silverlight parts. That means the WPF/SL application resources dictionaries are also separate. So the easiest way to handle different properties is to use styles. Shared .xaml file specifies just the control and its style. All necessary properties for WPF are defined in the style stored in the WPF application resources dictionary and the same is done for Silverlight.