5

I have control thats inherits from textbox

public class MyTextBox : TextBox

This has a style

<Style TargetType="{x:Type Controls:MyTextBox}">

one of the Setters is

<Setter Property="Template">

I want to be able to set the Binding.ValidationRules to something in the template, thus affecting all instances of this type of textbox. I can therefore make textboxes for say Times, Dates, Numerics, post/zip codes.. or whatever i want,

I don't want to have to set the validation rules every time i create a textbox. I just want to say i want a NumericTextBox and have it validate in whatever way is set in the template.

Is this possible?

All i have seen so far is the ValidationRules being set on each instance of the control e.g.

<TextBox x:Name="txtEMail" Template={StaticResource TextBoxErrorTemplate}>
<TextBox.Text>
    <Binding Path="EMail" UpdateSourceTrigger="PropertyChanged" >
        <Binding.ValidationRules>
            <local:RegexValidationRule Pattern="{StaticResource emailRegex}"/>
        </Binding.ValidationRules>
    </Binding>
</TextBox.Text>

(from http://www.wpftutorial.net/DataValidation.html)

H.B.
  • 166,899
  • 29
  • 327
  • 400
S Rosam
  • 375
  • 1
  • 3
  • 16

2 Answers2

4

As you see, validation rules are set along with bindings. I came across the same problem and the working solution for me was to do something like this:

    public MyTextBox()
    {            
        this.Loaded += new RoutedEventHandler(MyTextBox_Loaded);
    }

    void MyTextBox_Loaded(object sender, RoutedEventArgs e)
    {
        var binding = BindingOperations.GetBinding(this, TextBox.ValueProperty);
        binding.ValidationRules.Add(new MyValidationRule());
    }

The problem here is to be sure that the binding is set before we add the validation rule, hence the use of Loaded, but i'm not sure if this will work on every scenario.

Natxo
  • 2,917
  • 1
  • 24
  • 36
  • Hmm. okay. so how does this fit in with mvvm. should we be putting this binding and validation connection in the code behind? Would it be just as easy/hard to do each bonding on the xaml and forget templating in the way i had imagined? – S Rosam Sep 05 '11 at 19:29
  • This approach is architecture agnostic, and is to be used for general validations, otherwise i dont't see the point of creating a new class inheriting from textbox. In your example you needed to check for a valid email. If you need app specific data validation, you should always go with IDataErrorInfo. – Natxo Sep 06 '11 at 07:29
  • Yes, I think with usercontrols its okay to have code in the code behind. its a user control, it does a specific job and can ensure its data is valid. – S Rosam Sep 09 '11 at 06:47
  • That's it. Anyway, using codebehind in any control doesn't mean to break the MVVM, as long as it's used only to manage the UI. – Natxo Sep 09 '11 at 07:45
1

I am not sure it is possible to do exactly what you want. You might be able to do it with a lot of trickery in property setters (I wouldn't rely on this, since it would involve modifying bindings, which are by definition dynamic), or with code behind/custom controls.

Instead I suggest you push your validation into your ViewModel, probably with IDataErrorInfo. There are many articles out there. Here's one of the first ones I found with a search just now for "MVVM validation":

MVVM - Validation

Doing this will allow you to use standard OO composition techniques, so you can avoid repeating yourself :)

Community
  • 1
  • 1
Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183