Matthew Bonig
Matthew Bonig

Reputation: 2136

WPF/XAML: ExceptionValidationRule different when applying in code vs markup?

I've run across the need to apply the ExceptionValidationRule to many textboxes on a form in WPF. I can do this with markup and I get the desired result (the textbox gets a red outline when an invalid value is entered) but only when I supply the rule in markup:

<TextBox x:Name="Name" Width="150" >
    <TextBox.Text>
         <Binding Path="Name" Mode="TwoWay"  UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
              <Binding.ValidationRules>
                   <ExceptionValidationRule />
              </Binding.ValidationRules>
         </Binding>
    </TextBox.Text>
 </TextBox>

But when I apply the value using code:

Name.GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules.Add(new ExceptionValidationRule());

I don't get the desired results. This code is applied in a userControl's constructor after the InitalizeComponent() call. The user control has the textbox "Name" as a child control.

I've gone through and I can see, when using both, that two validation rules are put in the ValidationRules collection but when I am using just the code version I don't get the desired result of a red outline around the textbox when an invalid value is entered.

Am I just misunderstanding a fundamental rule to WPF?

Or, is there a way I can apply this validation rule using a Style? I'd prefer that, to tell you the truth.

Thanks, M

Upvotes: 2

Views: 681

Answers (1)

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84656

You can't change a Binding after it has been used, and apperently that goes for the ValidationRules as well. You can create a new Binding in code but that's probably not what you're after.

Binding binding = new Binding("Name");
binding.Mode = BindingMode.TwoWay;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
binding.NotifyOnValidationError = true;
binding.ValidationRules.Add(new ExceptionValidationRule());
nameTextBox.SetBinding(TextBox.TextProperty, binding);

A Style won't work either since a Binding or ValidationRule doesn't derive from FrameworkElement. What I would do in your situation is a subclassed Binding where you add all the things you need. Something like this

<TextBox x:Name="Name" Width="150" >    
    <TextBox.Text>    
        <local:ExBinding Path="Name"
                         Mode="TwoWay"
                         UpdateSourceTrigger="PropertyChanged"/>
    </TextBox.Text>
</TextBox>

The ExBinding, adding ValidationRule etc.

public class ExBinding : Binding
{
    public ExBinding()
        : base()
    {
        NotifyOnValidationError = true;
        ValidationRules.Add(new ExceptionValidationRule());
    }
}

Upvotes: 2

Related Questions