#141 – Dependency Property Value Sources: #7 – Style Setters

The seventh source in the list of sources for the base value of a dependency property is a style setter. A property obtains its value from a style setter when a style is applied to the parent element and the property’s value is set using a Setter in that style.

In the example below, a button has the style redBlueTextButton applied to it. This style sets the Foreground property to red using a Setter.  It also sets the property to blue when you hover the mouse over the control. The source of the Foreground property is style (style setter) to start with and then becomes style trigger when you move the mouse over the control.

    <Window.Resources>
        <Style x:Key="redBlueTextButton" TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="Red"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Foreground" Value="Blue"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <Button Content="Run" Height="23" Width="75" Style="{StaticResource redBlueTextButton}"/>
        <Button Content="Skip" Height="23" Width="75"/>
    </StackPanel>
Advertisement

#140 – Dependency Property Value Sources: #6 – Template Triggers

The sixth source in the list of sources for the base value of a dependency property is a template trigger. A property obtains its value from a template trigger when the element that the property belongs to has a template containing a trigger that changes the property.

In the example below, we apply a template to the main button, replacing it with two labels and a new button.  The trigger changes the Foreground property of the original button, so the property source for that property becomes template trigger.

The original button is replaced by the controls in the template, but its Foreground property is preserved by using the TemplateBinding markup extension.

        <Button Name="btnWithTemplate" Content="Recreate Me">
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <StackPanel Orientation="Horizontal">
                        <Label Content="**" Foreground="{TemplateBinding Foreground}"/>
                        <Button Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"/>
                        <Label Content="**" Foreground="{TemplateBinding Foreground}"/>
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Foreground" Value="Green"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>

#139 – Dependency Property Value Sources: #5 – Style Triggers

The fifth source in the list of sources for the base value of a dependency property is a style trigger. A property obtains its value from a style trigger when a style is applied to the parent element and the property’s value changes as a result of a trigger firing.

In the example below, a button has the style blueTextButton applied to it.  This style sets the Foreground property to blue when you hover the mouse over the control.  The source of the Foreground property then becomes style trigger when the trigger fires.

    <Window.Resources>
        <Style x:Key="blueTextButton">
            <Style.Triggers>
                <Trigger Property="Button.IsMouseOver" Value="True">
                    <Setter Property="Button.Foreground" Value="Blue"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <Button Content="Run" Height="23" Width="75" Style="{StaticResource blueTextButton}" />
        <Button Content="Skip" Height="23" Width="75" />
    </StackPanel>

#138 – Dependency Property Value Sources: #4 – Implicit Style

The fourth source in the list of sources for the base value of a dependency property is an implicit style.  This rule applies only to the Style dependency property.

The Style property obtains its value implicitly when a style is applied to all elements whose type matches the specified TargetType of the style.

Since an explicit style is treated as a local value, the resulting precedence list for the Style property, highest to lowest, is:

  • Explicit style (local value)
  • Implicit style
  • Default value

In the example below, we use an implicit style to set the style of two different Button elements.

    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Control.FontStyle" Value="Italic"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="Click Me" Height="23" Width="125" />
        <Button Content="Or Me" Height="23" Width="125" />
    </StackPanel>

#137 – The Value of the Style Property Comes From One of Three Places

The Style property is the one dependency property that doesn’t follow the full list of property value precedence rules.  Its value can come from one of three different sources, listed below.

  1. Explicit style – Style is explicitly specified, either inline in XAML, as a resource, or specified in code.  Treated as a local value
  2. Implicit style – Style is applied to all elements whose type matches the target type of the style
  3. Default – No style is specified, default styling used

Here’s an example of an explicit style.

    <Window.Resources>
        <Style x:Key="anItalicButton">
            <Setter Property="Control.FontStyle" Value="Italic"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="Click Me" Height="23" Width="125" Style="{StaticResource anItalicButton}"/>
        <Button Content="Or Me" Height="23" Width="125" />
    </StackPanel>

Here’s an example of an implicit style, applied to all Button elements.

    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Control.FontStyle" Value="Italic"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="Click Me" Height="23" Width="125" />
        <Button Content="Or Me" Height="23" Width="125" />
    </StackPanel>

#136 – Dependency Property Value Sources: #3 – Parent Template

The third source in the list of sources for the base value of a dependency property is a parent template.  A property obtains its value from a parent template if the element for which the property is being set was created as part of a template and it doesn’t obtain its value through a trigger.

In the example below, the excitedLabel template has two child Label controls.  The first one has its Background property set in the template, so the source of the base value is the parent template.

    <Window.Resources>
        <ControlTemplate x:Key="excitedLabel" TargetType="Label">
            <StackPanel Orientation="Horizontal">
                <Label Name="theYee" Background="AliceBlue" Content="Yee!"/>
                <ContentPresenter />
                <Label Name="theHaw" Content="Haw!"/>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <Label Content="Run" />
        <Label Content="Skip" Template="{StaticResource excitedLabel}"/>
    </StackPanel>

#135 – Dependency Property Value Sources: #2 – Parent Template Trigger

The second source in the list of sources for the base value of a dependency property is a parent template trigger.  A property obtains its value from a parent template trigger if the element was created as part of a template and its value is being set by a trigger defined in the template.

In the example below, the excitedLabel template has two child Label controls whose Background property changes when you hover the mouse over the parent control.  When this happens, the source of their Background property becomes the parent template trigger.

    <Window.Resources>
        <ControlTemplate x:Key="excitedLabel" TargetType="Label">
            <StackPanel Orientation="Horizontal">
                <Label Name="theYee" Content="Yee!"/>
                <ContentPresenter />
                <Label Name="theHaw" Content="Haw!"/>
            </StackPanel>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="theHaw" Property="Background" Value="HotPink"/>
                    <Setter TargetName="theYee" Property="Background" Value="HotPink"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <Label Content="Run" />
        <Label Content="Skip" Template="{StaticResource excitedLabel}"/>
    </StackPanel>

#134 – Dependency Property Value Sources: #1 – Local Value

The highest priority source for the base value of a dependency property is the property’s local value, set in XAML for the element that owns the property, or set from code.  If a local value is provided, it will override all other possible sources for the base value of the property.

In the following example, the 2nd Label provides a local value for the FontStyle property, overriding the inherited value.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:m="clr-namespace:PersonLib;assembly=PersonLib"
        Title="MainWindow" Height="350" Width="525" FontStyle="Italic">
    <StackPanel Orientation="Vertical">
        <Button Content="Run" Height="23" Width="75" />
        <Button Content="Skip" Height="23" Width="75" />
        <StackPanel Orientation="Horizontal">
            <Label Content="Inside 2nd StackPanel"/>
            <Label x:Name="lblIndep" Content="I do my own FontStyle" FontStyle="Normal"/>
        </StackPanel>
    </StackPanel>
</Window>

You can also set a local value from code:

            lblIndep.FontStyle = FontStyles.Normal;

#133 – Where a Dependency Property Gets Its Value

Since the value of a dependency property can come from a variety of different sources, WPF uses a predetermined precedence for each possible source of a property value in order to determine the final value.

WPF determines the final value for a dependency property as follows:

  • Determine the base value, using the precedence rules listed below
  • Evaluate expressions
  • Apply animations
  • Coerce value  (implementing class might coerce to valid value)
  • Validate (implementing class may throw exception if value is invalid)

The base value of a property is obtained from one of the following sources, listed from highest to lowest precedence:

WPF works down the list until it finds a source that provides a value for the property.

#132 – Inherited Property Values Pass Through All Elements

When an element looks up the element tree for an inherited property value, it doesn’t stop when it hits an element that doesn’t define that particular property.  The element “looks” all of the way up the tree, to the root element.

In the example below, we set a value for the FontStyle in the top-level Window element.  That value is inherited by the Button elements further down the tree, even though their immediate parent–the StackPanel–does not have a FontStyle property.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:m="clr-namespace:PersonLib;assembly=PersonLib"
        Title="MainWindow" Height="350" Width="525" FontStyle="Italic">
    <StackPanel Orientation="Vertical">
        <Button Content="Run" Height="23" Width="75" />
        <Button Content="Skip" Height="23" Width="75" />
    </StackPanel>
</Window>