Nov 23

Markup extensions

Posted in Silverlight XAML      Comments Off on Markup extensions

Markup extensions allows you to extend the expressibility of XAML. You use markup extensions to escape the general treatment that attribute values get (by default, we’ve seen that they are treated as strings or that a type converter is used to convert them to the adequate type). Markup extension expressions are always delimited by the pair { }.

Currently, the Silverlight’s XAML parser understands only four markup extensions:

  • Binding: used in data bound scenarios for getting the value of an object at run time. This extension is implemented by the Binding class and you can set several of its property from XAML (ie, from the markup extension expression itself). We’ll return to this class in future posts, when we talk about data binding operations;
  • StaticResource: used for setting the value of a property to a resource  already defined in a resource dictionary (resource dictionaries are used for saving objects by key and it can be used in both XAML and code). The current release of Silverlight does not have any managed code class for supporting this type of markup extension (in other words, this is implemented in unmanaged code);
  • TemplateBinding: another binding which is implemented in unmanaged code only. You’ll use this binding in your templates when you want to link the value of a control’s property to the value of another object’s property of the templated control (once again, this is only intro stuff and we’ll come back to this topic in future posts);
  • Null: used for setting the value of a property to null. You might find this markup extension odd at first, but the truth is that there’s no other way to set a property to null in XAML (don’t forget that passing string would probably result in using a type converter). Another interesting thing you should keep in mind is that not all properties have a default value of null (to understand this, we’ll need to go into dependency properties – and yes, that will be the topic of a future post).

If you’ve been doing some WPF development, you’ll probably be thinking that Silverlight is not as extensible as WPF. For starters, there is no MarkupExtension base class (which is extended by all markup extensions). In practice,this means that you cannot create your own markup extensions. Finally,you should also notice that unlike WPF, you can only use markup extensions with the attribute value syntax. Again, this is happening due to the limitations I’ve mentioned before (Silverlight must be small and we can’t forget that it runs across several platforms/browsers)

I guess that it’s time to see an example. We’ll get started with the StaticResource markup extension:

        <SolidColorBrush x:Key="brush" Color="Green" />
    <Button Content="Say hi"
        Background="{StaticResource brush}" />

In the previous snippet, I’ve started by creating a new Canvas resource brush and I’ve identified it with the name brush. This is all you need to be able to reuse that resource in all the Canvas’ children objects’ properties that expect a brush (in the previous example, I’ve used that resource to fill the background color of a button). Resource dictionary usage has some gotchas, but I’ll leave that for a future post (after all, the main objective of this post is to look at markup extensions).

StaticResource and Binding markup extensions expect only a single value. However, Binding is implemented through a managed class and if you check its definition, you’ll see that it has several properties which you can also set from XAML. In this case, the syntax is simple: you can specify a value for the “default” property (which is Path, in the case of the Binding markup extension) and you should indicate all the other properties through the key=value pair entries (separated by comma). For instance, here’s an example of how you can set a binding:

<TextBlock Text="{Binding Content, ElementName=origin}" />

In the previous snippet, I’m binding the value of the Text property to another element defined through XAML which is named origin (I guess it could be a button since it has  a Content property). There’s lot of things to say about bindings but for now I’m only worried in showing you how to use them from XAML (through the markup extension syntax).

Before ending up, there’s still time for one more topic: escaping the { } in attributes. By default, whenever you pass the pair { } to an attribute value, the XAML parser will interpret it as a markup extension. If you need to set the value of an attribute to a value which contains that { } pair, you’ll need to escape it. Here’s how:

<TextBlock Text="{}{Binding Content, ElementName=origin}" />

As you can see, using the {} pair at the beginning of the attribute’s value is all that it takes to escape the rest of the expression. If you put the previous XAML in a user control, you’ll see the {Binding….} text on the browser when you load that  control.

I’ve only been playing with Silverlight for a few days (and I really haven’t done any real work with it). Even though it has lots of potentials, I must confess that I’m a little disappointed with the gotchas I’ve already found. I guess that they won’t matter much if you’re using a tool like Blend for creating the interface, but I must say that all these little things which don’t always work as expected are starting to make me think that I should probably be working with WPF instead where everything makes sense and works as expected…

And that’s it for now. Stay tuned for more on Silverlight.