views:

121

answers:

1

Hello,

I added a ValidateValueCallback to a DependencyProperty called A. Now in the validate callback, A shall be compared to the value of a DependencyProperty called B. But how to access the value of B in the static ValidateValueCallback method validateValue(object value)? Thanks for any hint!

Sample code:

class ValidateTest : DependencyObject
{
    public static DependencyProperty AProperty = DependencyProperty.Register("A", typeof(double), typeof(ValidateTest), new PropertyMetadata(), validateValue);
    public static DependencyProperty BProperty = DependencyProperty.Register("B", typeof(double), typeof(ValidateTest));


    static bool validateValue(object value)
    {
        // Given value shall be greater than 0 and smaller than B - but how to access the value of B?

        return (double)value > 0 && value <= /* how to access the value of B ? */
    }
}
+1  A: 

Validation callbacks are used as sanity checks for the given input value against a set of static constraints. In your validation callback, checking for a positive value is a correct use of the validation, but checking against another property is not. If you need to ensure a given value is less than a dependent property, you should use property coercion, like so:

public static DependencyProperty AProperty = DependencyProperty.Register("A", typeof(double), typeof(ValidateTest), new PropertyMetadata(1.0, null, coerceValue), validateValue);
public static DependencyProperty BProperty = DependencyProperty.Register("B", typeof(double), typeof(ValidateTest), new PropertyMetaData(bChanged));

static object coerceValue(DependencyObject d, object value)
{
    var bVal = (double)d.GetValue(BProperty);

    if ((double)value > bVal)
        return bVal;

    return value;
}

static bool validateValue(object value)
{
    return (double)value > 0;
}

While this won't throw an exception if you set A > B (like the ValidationCallback does), this is actually the desired behavior. Since you don't know the order in which the properties are set, you should therefore support the properties being set in any order.

We also need to tell WPF to coerce the value of property A if the value of B changes, as the coerced value could change:

static void bChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    d.CoerceValue(AProperty);
}
Abe Heidebrecht
Thank you very much for this detailed reply! Marked as answer. I first had to get used to this way (not throwing an exception), but well, seems to be the "official" way.
stefan.at.wpf