Dependency Property Value Precedence
Microsoft Silverlight will reach end of support after October 2021. Learn more.
This topic explains how the workings of the Silverlight property system can affect the value of a dependency property, and describes the precedence by which aspects of the property system apply to the effective value of a property.
This topic contains the following sections.
- Prerequisites
- The Silverlight Property System
- Dependency Properties Might Be "Set" in Multiple Places
- Dependency Property Setting Precedence List
- Templated Properties
- Style Property
- Binding
- Animations and Base Value
- Default Values
- Related Topics
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing dependency properties on Silverlight classes, and have read Dependency Properties Overview. To follow the examples in this topic, you should also understand XAML and know how to write Silverlight-based applications.
The Silverlight Property System
In the Silverlight property system, the value of dependency properties can be determined by a variety of factors and features, enabling features such as late binding, 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. 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.
Note: |
---|
The SDK documentation uses the terms "local value" or "locally set value" occasionally when discussing dependency properties. A locally set value is a property value that is set directly on an object instance in code, or as an attribute on an element in XAML. |
Dependency Properties Might Be "Set" in Multiple Places
In the following example, the Background property has two different "set" operations that might influence the value.
<StackPanel.Resources>
<Style x:Key="ImmediateStyle" TargetType="Button">
<Setter Property="Background" Value="Green"/>
</Style>
</StackPanel.Resources>
<Button Style="{StaticResource ImmediateStyle}" Background="Red">
<TextBlock>Hello</TextBlock>
</Button>
Here, which color do you expect will apply—red or green?
With the exception of animated values, local property values are at the highest precedence. If you set a value locally, you can expect that the local value will be honored. In the preceding example, Background is set to Red locally. If you removed the local value of Red from that Button instance, then the Style.Setters value Green would apply.
Why Does the Dependency Property Precedence Concept Exist?
Typically, you would not want styles to always apply and to obscure even a locally set value of an individual element (otherwise, it would be very difficult to use either styles or elements in general). Therefore, the values that come from styles operate at a lower precedent than a locally set value.
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 Dependency Properties Overview.
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 Animations and Base Value later in this topic. In order to be animated, the dependency property must be a property type that the existing animation classes will support.
Local value. A local value might be set through the convenience of the CLR wrapper property, which also equates to setting as an attribute or property element in XAML, or by a call to the SetValue method using a property of a specific instance. If you set a local value by using a binding or a static resource, these each act in the precedence as if a local value was set.
Templated properties. An element has these if it was created as part of a template (a ControlTemplate or DataTemplate).
Style setters. Values from a Setter within styles from page or application resources.
Default value. Any given dependency property may have a default value. For details, see Default Values later in this topic.
Templated Properties
Templated properties as a precedence item does not apply to any property of an element that you declare directly in page markup. The templated property concept exists only for objects within an object tree that come into existence through the application of the template. When the property system searches the templated properties for a value, it is searching the template that created that object. The property values from the template generally act as if they were set as a local value on the object, but must be distinguishable from a true local value.
Note that depending on how the template is constructed, the template might override even local values, if the template failed to provide TemplateBinding references for relevant settable properties as they should appear in the template elements. This is usually only done if the property in question is an inherited property that is deemed to not have an analogous property in the specific template and visual design.
Style Property
The order of lookup described earlier applies to all possible dependency properties except one: the Style property. The Style property is unique in that it cannot itself be styled. Also, because there is no animation type for it, it cannot be animated.
Binding
Binding operations are treated as if they were setting the value to which they are being applied. For example, a binding applied to a local value acts as local value, and a binding for a property setter within a style applies as a style setter does. Because bindings must 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 run time as well.
Not only do bindings operate at the same precedence as a local value, they really are a local value, but with a value that is deferred. If you have a binding in place for a property value, any local value that you set subsequently replaces the binding entirely. Similarly, if you call SetBinding, you replace the previous local value.
Animations and Base Value
Animations act on a value that is termed as the "base value" throughout this documentation. The base value is thus whatever value is determined through evaluating upwards in the precedence until "local value" is reached.
For an animated property, 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. Afterwards, normal precedence is used for the base value determination.
Conversely, an animation that specifies a "To" with a "Hold" behavior can override a local value until the animation is removed, even when it visually appears to be stopped.
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.
Default Values
At the architecture level, default values for Silverlight dependency properties are generally one of the following:
A reference-type dependency property default value is null.
A value-type dependency property default value is the default-constructed value. For primitives, this leads to expected defaults such as 0 for int and double. For structures such as Point or custom structures, this uses the implicit default constructor. For enumerations, the default is the first defined member.
A string-type dependency property default value is an empty string.
Beyond these values, specific Silverlight dependency properties sometimes impose a default value through native implementation.
Custom dependency properties can specify a default value in metadata. For details, see Custom Dependency Objects and Dependency Properties.