Summary of Chapter 12. Styles

Download Sample Download the sample

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.

In Xamarin.Forms, styles allow multiple views to share a collection of property settings. This reduces markup and enables maintaining consistent visual themes.

Styles are almost always defined and consumed in markup. An object of type Style is instantiated in a resource dictionary and then set to the Style property of a visual element using a StaticResource or DynamicResource markup extension.

The basic Style

A Style requires that its TargetType be set to the type of the visual object it applies to. When a Style is instantiated in a resource dictionary (as is common) it also requires an x:Key attribute.

The Style has a content property of type Setters, which is a collection of Setter objects. Each Setter associates a Property with a Value.

In XAML the Property setting is the name of a CLR property (such as the Text property of Button) but the styled property must be backed by a bindable property. Also, the property must be defined in the class indicated by the TargetType setting, or inherited by that class.

You can specify the Value setting using the property element <Setter.Value>. This lets you set Value to an object that can't be expressed in a text string, or to an OnPlatform object, or to an object instantiated using x:Arguments or x:FactoryMethod. The Value property can also be set with a StaticResource expression to another item in the dictionary.

The BasicStyle program demonstrates the basic syntax and shows how to reference the Style with a StaticResource markup extension:

Triple screenshot of basic style

The Style object and any object created in the Style object as a Value setting are shared among all views referencing that Style. The Style cannot contain anything that cannot be shared, such as a View derivative.

Event handlers cannot be set in a Style. The GestureRecognizers property cannot be set in a Style because it is not backed by a bindable property.

Styles in code

Although it's not common, you can instantiate and initialize Style objects in code. This is demonstrated by the BasicStyleCode sample.

Style inheritance

Style has a BasedOn property that you can set to a StaticResource markup extension referencing another style. This allows styles to inherit from previous styles, and add or replace property settings. The StyleInheritance sample demonstrates this.

If Style2 is based on Style1, the TargetType of Style2 must be the same as Style1 or derived from Style1. The resource dictionary in which Style1 is stored must be the same resource dictionary as Style2 or a resource dictionary higher in the visual tree.

Implicit styles

If a Style in a resource dictionary does not have an x:Key attribute setting, it is assigned a dictionary key automatically, and the Style object becomes an implicit style. A view without a Style setting and whose type matches the TargetType exactly will find that style, as the ImplicitStyle sample demonstrates.

An implicit style can derive from a Style with an x:Key setting but not the other way around. You cannot explicitly reference an implicit style.

You can implement three types of hierarchy with styles and BasedOn:

  • From styles defined on the Application and Page down to styles defined on layouts lower in the visual tree.
  • From styles defined for base classes such as VisualElement and View to styles defined for specific classes.
  • From styles with explicit dictionary keys to implicit styles.

These hierarchies are demonstrated in the StyleHierarchy sample.

Dynamic styles

A style in a resource dictionary can be referenced by DynamicResource rather than StaticResource. This makes the style a dynamic style. If that style is replaced in the resource dictionary by another style with the same key, the views referencing that style with DynamicResource automatically change. Also, the absence of a dictionary entry with the specified key will cause StaticResource to raise an exception but not DynamicResource.

You can use this technique to dynamically change styling or themes as the DynamicStyles sample demonstrates.

However, you cannot set the BasedOn property to a DynamicResource makeup extension because BasedOn isn't backed by a bindable property. To derive a style dynamically, do not set BasedOn. Instead, set the BaseResourceKey property to the dictionary key of the style you want to derive from. The DynamicStylesInheritance sample demonstrates this technique.

Device styles

The Device.Styles nested class defines twelve static read-only fields for six styles with a TargetType of Label that you can use for common types of text usages.

Six of these fields are of type Style that you can set directly to a Style property in code:

The other six fields are of type string and can be used as dictionary keys for dynamic styles:

These styles are illustrated by the DeviceStylesList sample.