views:

889

answers:

1

Hi,

I tried to write my own Validation rule for a ComboBox, the rule is attached to the binding for SelectedItem - However it dosn't work. I've got similar rules working on the Text property ...

<ComboBox VerticalAlignment="Top" ItemsSource="{Binding Animals}" DisplayMemberPath="Name" >
        <ComboBox.SelectedItem>
            <Binding Path="Animal">
                <Binding.ValidationRules>
                    <validators:ComboBoxValidationRule ErrorMessage="Please select an animal" />
                </Binding.ValidationRules>
            </Binding>
        </ComboBox.SelectedItem>
    </ComboBox>

I think its down to the code I'm using to call the validation which I found on the net. Basically SelectedItem isn't coming up a dependency property.

It itterates through dependencyPropertyFields which contains TextProperty and SelectionBoxItemProperty but no SelectedItemProperty.

private void ValidateBindings(DependencyObject element)
    {
        Type elementType = element.GetType();

        FieldInfo[] dependencyPropertyFields = elementType.GetFields(
            BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);


        // Iterate over all dependency properties
        foreach (FieldInfo dependencyPropertyField in dependencyPropertyFields)
        {
            DependencyProperty dependencyProperty =
                dependencyPropertyField.GetValue(element) as DependencyProperty;

            if (dependencyProperty != null)
            {


                Binding binding = BindingOperations.GetBinding(element, dependencyProperty);


                BindingExpression bindingExpression = BindingOperations.GetBindingExpression(element, dependencyProperty);

                // Issue 1822 - Extra check added to prevent null reference exceptions
                if (binding != null && bindingExpression != null)
                {


                    // Validate the validation rules of the binding
                    foreach (ValidationRule rule in binding.ValidationRules)
                    {
                        ValidationResult result = rule.Validate(element.GetValue(dependencyProperty),
                            CultureInfo.CurrentCulture);

                        bindingExpression.UpdateSource();

                        if (!result.IsValid)
                        {
                            ErrorMessages.Add(result.ErrorContent.ToString());
                        }

                        IsContentValid &= result.IsValid;
                    }
                }
            }
        }
    }

Does anyway know where I'm going wrong?

Any help greatly appreciated!

Thanks,

Andy

+1  A: 

You aren't finding the SelectedItemProperty, because ComboBox doesn't have a SelectedItemProperty field, instead it is inheriting that from it's base class Selector. Of course, Selector and ComboBox don't have all the properties that you could possibly bind to either, you'll have to traverse all the way back to UIElement to find most of the inherited properties.

If you insert something to traverse the inheritance hierarchy then you can get all of the fields, and the validation rule will fire.

List<FieldInfo> dependencyPropertyFields = elementType.GetFields(
 BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).ToList();

// Iterate through the fields defined on any base types as well
Type baseType = elementType.BaseType;
while (baseType != null)
{
 dependencyPropertyFields.AddRange(
  baseType.GetFields(
   BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly));

 baseType = baseType.BaseType;
}
rmoore
Thanks very much for that, worked a treat!
Andy Clarke