Resources, styles and themes
A style sets a group of properties on every control it applies to, so a look is defined once and reused. Resources hold styles, templates, brushes and any other value under a key. A theme is a resource dictionary of styles for every control; IcyUI ships one, and you can replace or extend it.
Resources
Every element has a Resources dictionary. {StaticResource Key} looks a key up in the element's
own resources, then in each enclosing element of the same markup document, and uses the first match. It's resolved
once, while the document loads, so declare Resources before the children that use them; a key that isn't found is a
markup error.
A dictionary can merge others (MergedDictionaries), including resource-dictionary files loaded through the asset
pipeline. See Resources and styles in the markup reference for the syntax.
Styles
A Style has a TargetType, property values (its attributes in markup), and optional visual
states.
- Implicit (no
x:Key): applies to every control of exactly that type, in the element that declares it and below, that has no style of its own. - Keyed (
x:Key): applies where a control names it,Style="{StaticResource Key}". BasedOn: a style can start from another one's values and change some of them.
<!-- A keyed style based on another: BasedOn reuses its setters, and the theme still supplies the button's template. -->
<StackPanel Orientation="Vertical" Width="220">
<StackPanel.Resources>
<Style x:Key="MenuButton" TargetType="Button" Padding="24,8" HorizontalAlignment="Stretch" />
<Style x:Key="DangerButton" TargetType="Button" BasedOn="{StaticResource MenuButton}" Background="#FFB03A3A" />
</StackPanel.Resources>
<Button Style="{StaticResource MenuButton}" Margin="0,0,0,8">Continue</Button>
<Button Style="{StaticResource DangerButton}">Quit</Button>
</StackPanel>
The theme underneath
The theme's styles are the implicit styles of every built-in control, held by the canvas. A style of your own, keyed or
implicit, is applied on top of the theme's style for its type: the theme supplies the template, colors and visual
states, and your style changes only what it sets. In the example, DangerButton keeps the theme's button template and
changes only its background, padding and alignment. A visual state group in your style with the same name as one of the
theme's replaces that group (see what names are for).
To take the theme's look off a control entirely, set ReplacesTheme="True" on its style; the style then has to provide
everything itself, including a template.
To change the look of your game, layer a theme file over the built-in theme with ExtendDefaultTheme, or replace the
theme with UseThemeFile; see Custom themes.
Which value wins
A property can get its value from several places. The highest one present wins:
- a local value: set on the element in markup or code;
- a running animation;
- an active visual state (hovered, pressed, ...);
- a style (yours, over the theme's);
- the property's default.
So <Button Background="Red"/> stays red when hovered (local beats visual state), and a value set in code beats the
style. A local value equal to the default still counts: HorizontalAlignment="Stretch" on a button overrides the
theme's centered alignment.
Pitfalls
- Implicit styles match the exact type. A
Buttonstyle doesn't apply to aToggleButton; give each type its own, or base one on the other. {StaticResource}doesn't see the theme or the canvas. It searches the document being loaded; reach theme values through implicit styles instead.- Text properties don't inherit.
FontSizeorForegroundon a panel doesn't reach the text inside it; use an implicitTextBlockstyle in the panel's resources.
See also
- Control templates and visual states.
- Resources and styles in the markup reference.
- Buttons for the states each control's style uses.