Previously I did a post on the “Control Local Values bug” and how a subtle bug can be introduced when setting dependency properties of controls to local values. In WPF 4.0 (dev10), a mechanism was added to the property engine to solve this problem. Here are the new APIs in dev10:
Basically, when using DependencyObject.SetCurrentValue instead of DependencyObject.SetValue you set its effective value but its ValueSource remains the same. This is very similar to coercion.
Sample Test App
To make it more clear, I wrote a sample test app that shows the BaseValueSource and ValueSource properties when changing a DependencyProperty (DP) via SetCurrentValue. I created a custom control with a DP, TitleProperty, where I track its values. In addition, I setup several scenarios where the TitleProperty is initially set by a particular BaseValueSource. I’ll go through one scenario here.
I setup the custom control where the TitleProperty is set from a Style with a binding.
Initially it will look like this:
Notice the BaseValueSource is ‘Style’, IsExpression is ‘True’, and IsCurrent is ‘False’ as expected. After pressing the “Set Current Value” button the values will update accordingly:
Now the local value has updated to a new string that I set and IsCurrent has updated to ‘True’. Also notice that BaseValueSource and IsExpression have not changed which is also expected. If you press “Clear Local Value” the values will update back to their initial values. Now to bring back the original issue with the control local values bug, if you were to set or clear the local value any previous BaseValueSource would be overwritten and any expression lost. I have created other scenarios in the sample with different BaseValueSource behavior so you can understand how setting the current value behaves in those scenarios. Please be sure to check it out below.
For a control developer, the general recommendation is to always use DependencyObject.SetCurrentValue over DependencyObject.SetValue in Control code. You’ll notice that our stock controls in the 4.0 framework have all been updated to use this API instead of setting the properties with local values.