Silverlight and WPF Single-Sourcing – XAML namespaces

I have found that WPF and Silverlight XAML are sufficiently different to make single-sourcing difficult.

At first I did not know if it was possible at all, but I knew one thing – the differences in usage of namespaces look like something very annoying for which there must be an elegant solution.

The Problem

The first issue was with the standard controls which are in WPF 4.0 but not in Silverlight 3.0 (only in the toolkit), e.g. the Expander is declared like this in WPF,

<Expander … />

But it is declared like this in Silverlight,

… xmlns:Controls1="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" …
<
Controls1:Expander … />

What I really did not understand was that there is a similar problem when the standard controls which are in WPF 4.0 also are in Silverlight 3.0; for example, the HierarchicalDataTemplate is declared like this in WPF,

<HierarchicalDataTemplate … />

But it is declared like this in Silverlight,

… xmlns:Windows="clr-namespace:System.Windows;assembly=System.Windows.Controls" …
<
Windows:HierarchicalDataTemplate … />

Clearly the rules for defaulting and declaring namespaces are different.

The First Solution

I searched the Internet and found a few suggestions. One suggestion is to have two sets of name space references. This works because you are allowed to use name spaces on WPF although it is not mandatory. I did not like it because it still meant maintaining different files since XAML does not allow #IFDEF-like constructs.

My colleague David Anson found a surprisingly simple solution which he describes in a blog post (see the last bullet in the notes at the end of the post). The main idea is to subclass standard controls, effectively bringing them into the same namespace across Silverlight and WPF.

It looks like magic – and ReSharper also claims that this is not valid – but it works. Well, it almost works.

The Problem with the First Solution

So far I have found one problem with the first solution – the HierarchicalDataTemplate.

If I used David’s trick,

public class HierarchicalDataTemplate : System.Windows.HierarchicalDataTemplate { }

xmlns:Std="clr-namespace:Microsoft.Dynamics.Ax.Frameworks.Controls.StandardControls"

41: <Std:HierarchicalDataTemplate x:Key="hierarchicalDataTemplate" ItemsSource="{Binding Path=Subcomponents}">
42:    <StackPanel Orientation="Horizontal">
43:        <
Image Source="{Binding Path=TreeIcon}"/>
44:        <TextBlock Text="{Binding Path=Name}"/>
45:    </StackPanel>
46: </
Std:HierarchicalDataTemplate>

Then it compiled in Silverlight and WPF but the StackPanel caused problems at run-time in WPF. The error was

‘StackPanel’ object cannot be added to ‘HierarchicalDataTemplate’. Object of type ‘System.Windows.Controls.StackPanel’ cannot be converted to type ‘System.Windows.FrameworkElementFactory’.  Error at object ‘System.Windows.Controls.StackPanel’ in markup file ‘Microsoft.Dynamics.Ax.Frameworks.Controls;component/singlesourcetest.xaml’ Line 42 Position 26.

It did not help to use David’s trick again and add StackPanel to the Std namespace.

This is a WPF bug. It has not been fixed in the WPF 4.0 beta I am using but I hope it will be fixed eventually in the RTM.

The Second Solution

David worked hard on this problem and got another brilliant idea; if this is a problem with WPF only then why not subclass in Silverlight only? This requires a little trick that left David "a little slimy" – see his blog post for the details – but it works. Well, it almost works.

The Problem with the Second Solution

I took the sample project from the blog post for a spin and found that it would not work if I added x:Name="myTreeview" to the TreeView in XAML. This is the error I got,

The type ‘System.Windows.Controls.TreeView’ exists in both ‘c:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.Windows.Controls.dll’ and ‘e: \SharingXamlSilverlightWpf\PresentationFramework\Bin\Debug\PresentationFramework.dll’                e:\enlistments\axmain6\source\frameworks\controls\sharingxamlsilverlightwpf\sharingxamlsilverlightwpf-sl\obj\debug\mainpage.g.cs      38           42           SharingXamlSilverlightWpf-SL

Clearly there is a problem with disambiguating identical names across assemblies.

I needed to reference the name of the tree from a details view so I could not use the second solution for at least the controls that I needed to name.

But since the second solution seemed to only be needed for HierarchicalDataTemplate anyway, I am now using the first solution for everything but the HierarchicalDataTemplate.

And this works. Well, it almost works. But the remaining problems seem to be unrelated to this single-sourcing approach so I will defer blogging about it till later.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s