Expandos in xaml

Expandos in xaml

This post has a couple of suggestions on ways to accomplish expandos in Xaml. First some background …

On an HTML page you can define your own new “expando” properties on the fly, such as in this example:

<HTML>

<BODYonload='paragraph1.innerText = paragraph1.testing'>

<PID='paragraph1'testing='1, 2, 3'/>

</BODY>

</HTML>

Here I invented a new property named ‘testing’.I can both set that property and get it (the two parts in yellow above).

That’s a good feature when you want it.It’s a frustrating feature when you don’t.For example, in the following markup, I misspelled the “bgcolor” attribute.I’d like to be told that this is invalid, but instead it’s assumed to simply be an expando property.

<HTML>

<BODYbgcolour='red' >

<P>Hello</P>

</BODY>

</HTML>

It’s for this reason that the Xaml language is strongly-typed.E.g. the following is a compile/load error (the “BGround” should be “Background”):

<TextBlockBGround='Red'>Hello</TextBlock>

But then if you do want an expando, how do you do it?

One way is to actually define the properties you want to use, as attached properties.For example, this markup uses the ‘MyProperties.Testing’ attached property to set a property onto an unsuspecting TextBlock:

<Window x:Class="WPFApplication1.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:local="clr-namespace:MyNamespace" >

<TextBlocklocal:MyProperties.Testing='1, 2, 3' >Hello</TextBlock>

</Window>

.. where the code for MyProperties looks like this:

namespace MyNamespace

{

publicstaticclassMyProperties

{

publicstaticstring GetTesting(FrameworkElement obj)

{

return (string)obj.GetValue(TestingProperty);

}

publicstaticvoid SetTesting(FrameworkElement obj, string value)

{

obj.SetValue(TestingProperty, value);

}

// Using a DependencyProperty as the backing store for Testing.This enables animation, styling, binding, etc...

If you don’t want to write any code, you can do it all in markup, though it takes more markup than the HTML case.

First of all, recognize that expandos are really just a property bag of key/value pairs.So in the first HTML example above the P element has a dictionary item that maps the key “testing” to the value ”1,2,3”.In WPF you can get a real dictionary using the built-in Hashtable class.(You can’t use the Dictionary<K,T> class, because Generics aren’t supported in Xaml.)There’s also a Tag property on all elements to hold your random data.Put those two together and you can do something like the following:

<Page

xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'

xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'

xmlns:col='clr-namespace:System.Collections;assembly=mscorlib.dll'

xmlns:sys='clr-namespace:System;assembly=mscorlib'

Name='Page1' >

<Page.Tag>

<col:Hashtable>

<sys:Stringx:Key='testing'>1, 2, 3</sys:String>

<sys:Stringx:Key='anotherOne'>foo</sys:String>

<sys:Stringx:Key='yetAnotherOne'>bar</sys:String>

</col:Hashtable>

</Page.Tag>

<!-- This TextBlock.Text Binding queries a property out

of the dictionary -->

<TextBlockText='{Binding Tag[testing], ElementName=Page1}' />

</Page>

Update:Another common use of expando properties is to “comment out” an attribute, since XML doesn’t provide a built-in means to do so.I was just reading an old post on Chuck’s blog, and he shows there a way to do this in Xaml by using the markup compatibility feature.