OK, so more XAML mojo and sexiness from me :)
Markup extensions are another way of extending XAML expressiveness (like type converters), and making our XAML even more compact. WPF already comes with many built-in markup extensions out of the box, but as with anything else, it doesn’t stop us from creating our own.
We can also see a bunch of classes that derive from it. These are our ‘Mark Up’ extensions, and exploring these will give you a good idea of what each one does. These are also all available via the XAML language namespace, generally prefixed using x (as opposed to the WPF controls namespace which is normally the default namespace).
Let’s show an example.
Say we have a Button with an Ellipse as its content
And for some odd reason, we want to set the content property to Null. We cannot do this using normal property element syntax, so instead, we use property attribute syntax and use a Markup Extension to inject the Null value into the content property, like so
If you’re sharp enough, you may have noticed that I have omitted the ‘Extension’ part of the name, this is allowed by WPF as a form of shorthand notation (though you can very well write the full name).
If you explorer the Object Browser further, you will also note that Binding, Static, Array, RelativeSource, etc… are all actually markup extensions.
There is nothing stopping you from defining your own markup extensions, though you need to remember to import these as a namespace prior to using them, and that they must extend from System.Windows.Markup.MarkupExtension… otherwise the XAML parser WILL complain :)
One other note. It is also allowed to nest markup extensions ad-inifintum, the most common example being the following:
If you noticed, some parameters are prefixed (like Path=) whilst others are not. The ones that are not are fed to the extension’s constructor as a string parameter, whilst the others are fed into the already-constructed object’s property setters. So, in the example above, ‘RelativeSource=’ is referring to the Binding.setRelativeSource(…) setter, and feeding into it a RelativeSource object that has been constructed as new RelativeSource(“self”)… hope this clarifies a few things :)