Summary of Chapter 10. XAML markup extensions
Note
This book was published in the spring of 2016, and has not been updated since then. There is much in the book that remains valuable, but some of the material is outdated, and some topics are no longer entirely correct or complete.
Normally, the XAML parser converts any string set as an attribute value to the type of the property based on standard conversions for the basic .NET data types, or a TypeConverter
derivative attached to the property or its type with a TypeConverterAttribute
.
But it's sometimes convenient to set an attribute from a different source, for example, an item in a dictionary, or the value of a static property or field, or from a calculation of some sort.
This is the job of a XAML markup extension. Despite the name, XAML markup extensions are not an extension to XML. XAML is always legal XML.
The code infrastructure
A XAML markup extension is a class that implements the IMarkupExtension
interface. Such a class often has the word Extension
at the end of its name but usually appears in XAML without that suffix.
The following XAML markup extensions are supported by all implementations of XAML:
x:Static
supported byStaticExtension
x:Reference
supported byReferenceExtension
x:Type
supported byTypeExtension
x:Null
supported byNullExtension
x:Array
supported byArrayExtension
These four XAML markup extensions are supported by many implementations of XAML, including Xamarin.Forms:
StaticResource
supported byStaticResourceExtension
DynamicResource
supported byDynamicResourceExtension
Binding
supported byBindingExtension
—discussed in Chapter 16. Data bindingTemplateBinding
supported byTemplateBindingExtension
—not covered in the book
An additional XAML markup extension is included in Xamarin.Forms in connection with RelativeLayout
:
ConstraintExpression
—not covered in the book
Accessing static members
Use the x:Static
element to set an attribute to the value of a public static property, field, or enumeration member. Set the Member
property to the static member. It's usually easier to specify x:Static
and the member name in curly braces. The name of the Member
property does not need to be included, just the member itself. This common syntax is shown in the SharedStatics sample. The static fields themselves are defined in the AppConstants
class. This technique allows you to establish constants used through a program.
With an additional XML namespace declaration, you can reference public static properties, fields, or enumeration members defined in the .NET framework, as demonstrated in the SystemStatics sample.
Resource dictionaries
The VisualElement
class defines a property named Resources
that you can set to an object of type ResourceDictionary
. Within XAML, you can store items in this dictionary and identify them with the x:Key
attribute. The items stored in the resource dictionary are shared among all references to the item.
StaticResource for most purposes
In most cases you'll use the StaticResource
markup extension to reference an item from the resource dictionary, as demonstrated by the ResourceSharing sample. You can use a StaticResourceExtension
element or StaticResource
within curly braces:
Do not confuse the x:Static
markup extension and the StaticResource
markup extension.
A tree of dictionaries
When the XAML parser encounters a StaticResource
, it begins searching up the visual tree for a matching key, and then looks in the ResourceDictionary
in the application's App
class. This allows items in a resource dictionary deeper in the visual tree to override a resource dictionary higher in the visual tree. This is demonstrated in the ResourceTrees sample.
DynamicResource for special purposes
The StaticResource
markup extension causes an item to be retrieved from the dictionary when a visual tree is built during the InitializeComponent
call. An alternative to StaticResource
is DynamicResource
, which maintains a link to the dictionary key and updates the target when the item referenced by the key changes.
The difference between StaticResource
and DynamicResource
is demonstrated in the DynamicVsStatic sample.
A property set by DynamicResource
must be backed by a bindable property as discussed in Chapter 11, The bindable infrastructure.
Lesser-used markup extensions
Use the x:Null
markup extension to set a property to null
.
Use the x:Type
markup extension to set a property to a .NET Type
object.
Use x:Array
to define an array. Specify the type of the array members by setting the [Type
] property to an x:Type
markup extension.
A custom markup extension
You can create your own XAML markup extensions by writing a class that implements the IMarkupExtension
interface with a ProvideValue
method.
The HslColorExtension
class satisfies those requirement. It creates a value of type Color
based on values of properties named H
, S
, L
, and A
. This class is the first item in a Xamarin.Forms library named Xamarin.FormsBook.Toolkit that is built up and used over the course of this book.
The CustomExtensionDemo sample demonstrates how to reference this library and use the custom markup extension.