Partager via


Dependency Property Value Precedence

This topic explains how the workings of the Windows Presentation Foundation (WPF) property system can affect the value of a dependency property, and describes the precedence by which these factors apply to the effective value of a property.

This topic contains the following sections.

  • Prerequisites
  • The WPF Property System
  • Dependency Properties Might be "Set" in Multiple Places
  • Dependency Property Setting Precedence List
  • The Style Property
  • Dynamic Resource References and Binding
  • Coercion, Animations, and Base Value
  • Trigger Behaviors
  • ClearValue and Value Precedence
  • Related Topics

Prerequisites

This topic assumes that you understand dependency properties from the perspective of a consumer of existing dependency properties on WPF classes, and have read the Dependency Properties Overview topic. To follow the examples in this topic, you should also understand Extensible Application Markup Language (XAML) and know how to write WPF applications.

The WPF Property System

The WPF property system offers a powerful way to have the value of dependency properties be determined by a variety of factors, enabling features such as real-time property validation and notifying related properties of changes to values for other properties. The exact order and logic that is used to determine dependency property values is reasonably complex, and knowing this order will help you avoid unnecessary property setting, and might also clear up confusion over exactly why some attempt to influence or anticipate a dependency property value did not end up resulting in the value you expected.

Dependency Properties Might be "Set" in Multiple Places

The following is example XAML where the same property (Background) has three different "set" operations that might influence the value.

    <Button Background="Red">
      <Button.Style>
        <Style TargetType="{x:Type Button}">
          <Setter Property="Background" Value="Green"/>
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
              <Setter Property="Background" Value="Blue" />
            </Trigger>
          </Style.Triggers>
        </Style>
      </Button.Style>
Click
    </Button>

Here, which color do you expect will apply - red, green, or blue?

With the exception of animated values and coercion, local property sets are set at the highest precedence. If you set a value locally you can expect that the value will be honored, even above any styles or control templates. Here in the example, Background is set to Red locally. Therefore, the style defined in this scope, even though it is a type style which would otherwise apply to all elements of that type in that scope, is not the highest precedence for giving the Background property its value. If you removed the local value of Red from that Button instance, then the style would have precedence and the button would obtain the Background value from the style. Within the style, triggers take precedence, so the button will be blue if the mouse is over it, and green otherwise.

Dependency Property Setting Precedence List

The following is the definitive order that the property system uses when assigning the run-time values of dependency properties. Highest precedence is listed first. This list expands on some of the generalizations made in the Dependency Properties Overview.

  1. Property system coercion: For details on coercion, see Coercion, Animation, and Base Values section in this topic.

  2. Active animations, or animations with a Hold behavior: In order to have any practical effect, an animation of a property must be able to have precedence over the base (unanimated) value, even if that value was set locally. For details, see Coercion, Animation, and Base Values section in this topic.

  3. Local value: A local value might be set through the convenience of the "wrapper" property, which also equates to setting as an attribute or property element in XAML, or by a call to the SetValue API using a property of a specific instance.

  4. TemplatedParent template: An element has a TemplatedParent if it was created as part of a template (a ControlTemplate or DataTemplate, for example, of a style used either implicitly for the type or explicitly by key). When the property system searches the TemplatedParent template for a value, it is searching the template that created that element. The property values from the TemplatedParent template act as if they were set as a local value on the child element, but this secondary precedence is required because the templates are potentially shared. See TemplatedParent for details. Within a TemplatedParent template, the following order of precedence applies:

    1. Triggers from the TemplatedParent template.

    2. Setters from the TemplatedParent template.

  5. Style triggers: The triggers within explicit styles (referenced by non-type Key) from page or application.

  6. Template triggers: Any trigger from a template within a style or a directly applied template.

  7. Style setters: Values from a Setter within explicit styles (referenced by non-type Key), from page or application.

  8. Theme style: You may encounter the effects of theme styles in common controls (buttons, menus) or navigation level elements such as Window. Properties that are likely to be declared in theme styles include foreground and background, sizes and positioning of composited elements within a control, and certain behaviors such as triggers in scrollbars. Within a theme style, the following order of predence applies:

    1. Triggers in the theme style.

    2. Setters in the theme style.

  9. Inheritance: A few dependency properties inherit their values from parent element to child elements, such that they need not be set specifically on each element throughout an application. For details see Property Value Inheritance.

  10. Default value from dependency property metadata: Any given dependency property may have a default value as established by the property system registration of that particular property. Also, derived classes that inherit a dependency property have the option to override that metadata (including the default value) on a per-type basis. See Dependency Property Metadata for more information. Because inheritance is checked before default value, for an inherited property, a parent element default value takes precedence over a child element. Consequently, if an inheritable property is not set anywhere, the default value as specified on the root or parent is used instead of the child element default value.

The Style Property

The order of lookup described above applies to all possible dependency properties except one: the Style property. The Style property is unique in that it cannot be itself styled, so the precedence items 5 through 8 do not apply. Instead, replacing items 5 through 8 is a special determinant for the Style property: checking various levels of resources (page, application, theme) for an implicit style key that matches the type of the current element. If a matching implicit style is found, that style is applied as the Style property value, thus potentially influencing all of the other style considerations on other properties.

For implicit styles not in themes, the type must match exactly – a "MyButton" derived class will not implicitly use a style for "Button". For implicit styles from themes, the lookup uses a different value than the type of the element itself. The theme lookup instead uses the value of the DefaultStyleKey property. Because this property inherits, this means that at the theme level a "MyButton" derived class would in fact get the default style key for "Button." If you were the control author of "MyButton" and you want a different behavior, you can override the dependency property metadata for DefaultStyleKey on "MyButton" to return a different key. For more details on themes, styles and control authoring, see Control Authoring Overview.

Dynamic Resource References and Binding

Dynamic resource references and binding operations are both treated as if they were setting the value to which they are being applied. For instance, a dynamic resource applied to a local value acts per precedence item 3, a binding for a property setter within a theme style applies at precedence item 9, and so on. Because dynamic resource references and binding must both be able to obtain values from the run time state of the application, this entails that the actual process of determining the property value precedence for any given property extends into the run time as well.

Dynamic resource references are not strictly speaking part of the property system, but they do have a lookup order of their own which interacts with the sequence listed above. That precedence is documented more thoroughly in the Resources Overview. The basic summation of that precedence is: element to page root, application, theme, system.

Not only do dynamic resources and bindings operate at the same precedence as a local value, they really are a local value, but with a value that is deferred. One consequence of this is that if you have a dynamic resource or binding in place for a property value, any local value that you set subsequently replaces the dynamic binding or binding entirely. Even if you call ClearValue to clear the locally set value, the dynamic resource or binding will not be restored. In fact, if you call ClearValue on a property that has a dynamic resource or binding in place (with no "literal" local value), they are cleared by the ClearValue call too.

Coercion, Animations, and Base Value

Coercion and animation both act on a value that is termed as the "base value" throughout this SDK. The base value is thus whatever value is determined through evaluating upwards in the items until item 2 is reached.

For an animation, the base value can have an effect on the animated value, if that animation does not specify both "From" and "To" for certain behaviors, or if the animation deliberately reverts to the base value when completed. To see this in practice, run the From, To, and By Animation Target Values Sample. Try setting the local values of the rectangle height in the example, such that the initial local value differs from any "From" in the animation. You will note that the animations start right away using the "From" values and replace the base value once started. The animation might specify to return to the value found before animation once it is completed by specifying the Stop FillBehavior. Afterwards, normal precedence is used for the base value determination.

Multiple animations might be applied to a single property, with each of these animations possibly having been defined from different points in the value precedence. However, these animations will potentially composite their values, rather than just applying the animation from the higher precedence. This depends on exactly how the animations are defined, and the type of the value that is being animated. For more general information about animating properties, see Animation Overview.

Coercion applies at the highest level of all. Even an already running animation is subject to value coercion. Certain existing dependency properties in WPF have built-in coercion. For a custom dependency property, you define the coercion behavior for a custom dependency property by writing a CoerceValueCallback and passing the callback as part of metadata when you create the property. You can also override coercion behavior of existing properties by overriding the metadata on that property in a derived class. Coercion interacts with the base value in such a way that the constraints on coercion are applied as those constraints exist at the time, but the base value is still retained. Therefore, if constraints in coercion are later lifted, the coercion will return the closest value possible to that base value, and potentially the coercion influence on a property will cease as soon as all constraints are lifted. For more information about coercion behavior, see Dependency Property Callbacks and Validation.

Trigger Behaviors

Controls often define trigger behaviors as part of their default style in themes. Setting local properties on controls might prevent the triggers from being able to respond to user-driven events either visually or behaviorally. The most common use of a property trigger is for control or state properties such as IsSelected. For instance, by default when a Button is disabled (trigger for IsEnabled is false) then the Foreground value in the theme style is what causes the control to appear "grayed out". But if you have set a local Foreground value, that normal gray-out color will be overruled in precedence by your local property set, even in this property-triggered scenario. Be cautious of setting values for properties that have theme-level trigger behaviors and make sure you are not unduly interfering with the intended user experience for that control.

ClearValue and Value Precedence

The ClearValue method provides an expedient means to clear any locally applied value from a dependency property that is set on an element. However, calling ClearValue is not a guarantee that the default as established in metadata during property registration is the new effective value. All of the other participants in value precedence are still active. Only the locally set value has been removed from the precedence sequence. For instance, if you call ClearValue on a property where that property is also set by a theme style, then the theme value is applied as the new value rather than the metadata-based default. You can see this illustrated within the Restoring Default Values Sample although in this case the applied style is an application style. If you want to take all property value participants out of the process and set the value to the registered metadata default, you could obtain that default value definitively by querying the dependency property metadata, and then could use the default value to locally set the property with a call to SetValue.

See Also

Reference

DependencyObject
DependencyProperty

Concepts

Dependency Properties Overview
Custom Dependency Properties
Dependency Property Callbacks and Validation