แชร์ผ่าน


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:

These four XAML markup extensions are supported by many implementations of XAML, including Xamarin.Forms:

An additional XAML markup extension is included in Xamarin.Forms in connection with RelativeLayout:

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:

Triple screenshot of resource sharing

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.