The Avalon documentation is kind of sparse on this topic. There is a section called "Dependency Property Callbacks and Value Method Override" but it is blank!
I need to know exactly what happens when you get/set a DP or when other things happen to it like animation and such. I need to know how all the following fit into the pipeline:
DependencyObject.GetValue
DependencyObject.GetValueBase
DependencyObject.ReadLocalValue (why no WriteLocalValue )
DependencyObject.SetValue
DependencyObject.SetValueBase
DependencyObject.OnPropertyInvalidated
DependencyProperty.ValidateValueCallback
PropertyMetadata.GetValueOverride
PropertyMetadata.PropertyInvalidatedCallback
PropertyMetadata.ReadLocalValueOverride
PropertyMetadata.SetValueOverride
PropertyMetadata.WriteLocalValueOverride
PropertyMetadata.PropertyInvalidatedCallback
The actual scenario I'm dealing with is a property Z that, when read, is calculated from the values of some other properties A,B,C. However, when Z is written, A,B,C are recalculated from both Z and their own current values.
I also need to do complex clipping on some of the properties and the clipping boundaries are related to other properties. I want to put all of my clipping in a single method that is called after any value is changed.
Because of all this, a simple data binding+conversion won't work, so I'm trying to custom code the logic in get/set overrides. The problem is, I don't know which override to use (GetValueOverride or ReadLocalValueOverride), what that override should call (GetValue, GetValueBase, ReadLocalValue) or where the actual data should be stored.
What I really need is a detailed overview of the DP pipeline and where everything fits in.

Custom logic for dependency properties
Krixna
I made a custom control that coerces a property using GetValueOverride and it seems to work just fine with animation and binding! That is, the animation is properly clipped and bindings read the coerced value. And since the value is coerced in GetValue instead of SetValue, the un-coerced value is preserved and you get order independence.
So where is the problem And why does ScrollBar crash in the same situation Is it just a bug in the implementation of that particular control
jiggs
We spent a lot of time looking at different ways to do the scrollbar problem, and we couldn't see any right way with the September CTP property engine. The implementation of Scrollbar is exceedingly painful even with the limitations it has, this'll give you a flavor of what we had to do. (similar logic inside Maximum and Minimum properties, plus more logic when all three of those properties are invalidated)
public double Value
{
get
{
if (!_valueCacheValid)
{
_valueCache = (double)GetValueBase(ValueProperty);
// Has stored value changed since the last time we explicitly set
if (_previousCoercedValue != _valueCache)
{
// This might happen because the stored value came from DataBinding,
// or someone set value by calling SetValue() directly.
//
// Then the _desired value should be updated because the value that was set from
// our side is no longer valid.
_desiredValue = _previousCoercedValue = _valueCache;
}
// Coerce value now.
double newCoercedValue = Math.Min(Math.Max(_desiredValue, Minimum), Maximum);
if (newCoercedValue != _valueCache)
{
// Looks like we need to store a new coerced value.
_valueCache = _previousCoercedValue = newCoercedValue;
SetValue(ValueProperty, newCoercedValue);
}
_valueCacheValid = true;
}
return _valueCache;
}
set
{
if (double.IsInfinity(value))
{
throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, ValueProperty.Name));
}
// Store desired value privately.
_desiredValue = value;
_previousCoercedValue = Math.Min(Math.Max(_desiredValue, Minimum), Maximum);
// Store coerced value.
SetValue (ValueProperty, _previousCoercedValue);
}
}
You need to be really, really careful about order-dependent properties -- when you style something, there's no guarantee what order properties get set in. As you said, the ColorPicker sample does have this problem, that's because again there is no right way to solve it in the September CTP bits if you have mutually dependent properties. That's a reasonable short-term implementation until more options are available in future CTP's, but I suggest you think long and hard about what the order-independent semantics will be, to make sure they actually exist! After all, few things suck more than waiting for a "solution" that doesn't actually solve your problem.
(In the color picker scenario, the order-independent semantics are one of the properties gets ignored if the other is set -- eg, Color = (55,55,55); Red=90; GetRed()==55)
lordvr
The central requirement is your design needs to the order-independent -- properties can be set in any order and give the same results. E.g., take the example of Scrollbar's Min/Max/Value properties -- Value is supposed to be between Min and Max, but the properties can be set in any order -- scrollbar.Max = 100; scrollbar.Value = 200; scrollbar.Max = 300; should be perfectly valid. And reading Value will not return any more than the Max property, even though internally you need to remember the 200 -- the return value here is called the "coerced value".
But there's no right way to implement coerced values in the September CTP, every approach ignores either animations, data binding, or order-independence. A "typical" solution (order-independent but no data binding or animations) is to use SetValueOverride to stash away the set value (200 in the example above), and GetValueOverride to return the coerced value (100).
Jackson Lum
ThomasMG
I did some tests with ScrollBar and it seems to obey the order-independence rule and supports animations properly, so there must be some way to do it.
It's actually impossible to make my properties order-independent because the way different properties are bound together. Such is also the case with the ColorPicker sample that comes with the SDK. If you set both Color and Red, the final value of both will depend on the order they are set.