arrow-left arrow-right brightness-2 chevron-left chevron-right circle-half-full dots-horizontal facebook-box facebook loader magnify menu-down RSS star Twitter twitter GitHub white-balance-sunny window-close
Extending the WPF XML namespaces
2 min read

Extending the WPF XML namespaces

This is an old post and doesn't necessarily reflect my current thinking on a topic, and some links or images may not work. The text is preserved here for posterity.

Rob Relyea might not like this, but today I had an idea.

When referencing controls from another assembly in XAML, one can either use xmlns:foo="clr-namespace:MyNamespace;assembly=MyAssembly" syntax, or a URI mapped with the XmlnsDefinition attribute. MSDN can tell you all about the attribute. Currently in Magellan I use it like this:

[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Abstractions")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Commands")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Behaviors")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Controls")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Framework")]
[assembly: XmlnsDefinition("http://xamlforge.com/magellan", "Magellan.Views")]

This allows you to reference any Magellan object with a simple reference:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:magellan="http://xamlforge.com/magellan" 
    >

The annoying thing about this, though, is you end up with ugly prefixes all over the XAML:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:magellan="http://xamlforge.com/magellan" 
    x:Class="Wizard.Views.Shared.Main" 
    >
    <DockPanel>
        <magellan:ZonePlaceHolder ZoneName="Left" DockPanel.Dock="Left" Width="300" />
        <magellan:ZonePlaceHolder ZoneName="Right" DockPanel.Dock="Right" Width="300" />
        <magellan:ZonePlaceHolder ZoneName="Content" />
    </DockPanel>
</UserControl>

Today I had an idea: I can usurp the Microsoft WPF XML namespaces by adding my own controls to them. It would be as simple as changing my XmlnsDefinition attrbutes to:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Abstractions")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Commands")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Behaviors")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Controls")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Framework")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Magellan.Views")]

Which lets me use this:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Wizard.Views.Shared.Main" 
    >
    <DockPanel>
        <ZonePlaceHolder ZoneName="Left" DockPanel.Dock="Left" Width="300" />
        <ZonePlaceHolder ZoneName="Right" DockPanel.Dock="Right" Width="300" />
        <ZonePlaceHolder ZoneName="Content" />
    </DockPanel>
</UserControl>

Which not only reads nicer, but is also more accessible, since there's no need to manually add an import (ReSharper will add xmlns entries for you, but unfortunately it doesn't recognise XmlnsDefinition attributes).

My initial reaction is that this is evil, but in thinking about it, there are no Magellan classes that would conflict with classes in the WPF XML namespace. And if other libraries had the same names, you could use prefixes for those to differentiate, so that would just work. It also works fine in Blend. So the only problem that could arise is if someone else used this trick. But since it's so evil, I'd be the only one doing it, so there's no problem ;)

What do you think? Would you be disturbed by this, or would you actually find it a better experience?

Edit: It turns out that even if another library used this technique and was referenced, you can still differentiate between them by using an explicit xmlns:xyz reference. So I am not seeing much of a downside.

Paul Stovell's Blog

Hello, I'm Paul Stovell

I'm a Brisbane-based software developer, and founder of Octopus Deploy, a DevOps automation software company. This is my personal blog where I write about my journey with Octopus and software development.

I write new blog posts about once a month. Subscribe and I'll send you an email when I publish something new.

Subscribe

Comments