WPF Concepts—Support for Multiple Providers
| Visual C# Tutorials |
| .NET Framework Tutorials |
| © 2007 Sams Publishing |
Support for Multiple Providers
WPF contains many powerful mechanisms that independently attempt to set the value of dependency properties. Without a well-defined mechanism for handling these disparate property value providers, the system would be a bit chaotic and property values could be unstable. Of course, as their name indicates, dependency properties were designed to depend on these providers in a consistent and orderly manner.
Contents |
Figure 3.5 illustrates the five-step process that WPF runs each dependency property through in order to calculate its final value. This process happens automatically thanks to the built-in change notification in dependency properties.

Figure 3.5 The pipeline for calculating the value of a dependency property.
Step 1: Determine Base Value
Most of the property value providers factor into the base value calculation. The following list reveals the eight providers that can set the value of most dependency properties, in order from highest to lowest precedence:
- Local value
- Style triggers
- Template triggers
- Style setters
- Theme style triggers
- Theme style setters
- Property value inheritance
- Default value
You've already seen some of the property value providers, such as property value inheritance. Local value technically means any call to DependencyObject.SetValue, but this is typically seen with a simple property assignment in XAML or procedural code (because of the way dependency properties are implemented, as shown previously with Button.IsDefault). Default value refers to the initial value registered with the dependency property, which naturally has the lowest precedence. The other providers, which all involve styles and templates, are explained further in Chapter 10.
This order of precedence explains why StatusBar's FontSize and FontStyle were not impacted by property value inheritance in Listing 3.4. The setting of StatusBar's font properties to match system settings is done via theme style setters (#6 in the list). Although this has precedence over property value inheritance (#7 in the list), you can still override these font settings using any mechanism with a higher precedence, such as simply setting local values on the StatusBar.
Step 2: Evaluate
If the value from step one is an expression (an object deriving from System.Windows.Expression), then WPF performs a special evaluation step to convert the expression into a concrete result. In version 3.0 of WPF, expressions only come into play when using dynamic resources or data binding. Future versions of WPF may enable additional kinds of expressions.
Step 3: Apply Animations
If one or more animations are running, they have the power to alter the current property value (using the value after step 2 as input) or completely replace it. Therefore, animations can trump all other property value providers—even local values! This is often a stumbling block for people who are new to WPF.
Step 4: Coerce
After all the property value providers have had their say, WPF takes the almost-final property value and passes it to a CoerceValueCallback delegate, if one was registered with the dependency property. The callback is responsible for returning a new value, based on custom logic. For example, built-in WPF controls such as ProgressBar use this callback to constrain its Value dependency property to a value between its Minimum and Maximum values, returning Minimum if the input value is less than Minimum or Maximum if the input value is greater than Maximum.
Step 5: Validate
Finally, the potentially-coerced value is passed to a ValidateValueCallback delegate, if one was registered with the dependency property. This callback must return true if the input value is valid or false otherwise. Returning false causes an exception to be thrown, cancelling the entire process.
| TIP |
If you can't figure out where a given dependency property is getting its current value from, you can use the static DependencyPropertyHelper.GetValueSource method as a debugging aid. This returns a ValueSource structure that contains a few pieces of data: a BaseValueSource enumeration that reveals where the base value came from (step 1 in the process) and Boolean IsExpression, IsAnimated, and IsCoerced properties that reveal information about steps 2-4.
When calling this method on the StatusBar instance from Listing 3.1 or 3.4 with the Do not use this method in production code! Future versions of WPF could break assumptions you've made about the value calculation, plus treating a property value differently depending on its source goes against the way things are supposed to work in WPF applications. |
| Digging Deeper: Clearing a Local Value |
The earlier "Change Notification" section demonstrated the use of procedural code to change a Button's Foreground to blue in response to the MouseEnter event, and then changing it back to black in response to the MouseLeave event. The problem with this approach is that black is set as a local value inside MouseLeave, which is much different from the Button's initial state in which its black Foreground comes from a setter in its theme style. If the theme is changed and the new theme tries to change the default Foreground color (or if other providers with higher precedence try to do the same), it gets trumped by the local setting of black.
What you likely want to do instead is clear the local value and let WPF set the value from the relevant provider with the next-highest precedence. Fortunately, b.ClearValue(Button.ForegroundProperty); ( Note that the trigger on the |
|

