views:

489

answers:

2

I have the following Loaded event on my Window:

void Window_Loaded(object sender, RoutedEventArgs e) {
    this.DataContext = new MyObject() {
        MyDateTime = DateTime.Now,
        MyNotEmptyString = "Not Empty",
        MyNotUpperCaseString = "not upper case",
        MyInteger = 20,
        MyIntegerInRange = 1,
        MyDouble = 4.56
    };
}

For each property initialized above, I have a TextBox that binds to it, each having its own validation rule(s) associated with it.

The problem is, my Validation Rules are not being run the very first time when this.DataContext is set, but work great when the form is used normally (they are run when the TextBox loses focus). What could be the reason behind this? I tried setting UpdateSourceTrigger="PropertyChanged", but that didn't help.

Edit: Here is an example of a TextBox that is binding to a property:

<TextBox Name="MyDoubleField">
    <TextBox.Text>
        <Binding Path="MyDouble">
            <Binding.ValidationRules>
                <local:TextIsDouble/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
A: 

Is there a reason why your validation is not in your data classes? Using IDataErrorInfo should validate the data immediately and then bubble that up to your UI without having to do anything extra.

I say should, because this works for us, but we don't use WPF.

TheCodeMonk
I'm not sure if that's always possible (validation in my data classes) at all times. I'm working on a project that uses WCF and WPF, and the classes that the WPF client uses are auto-generated from the WCF Contracts. Unless there's a way to auto-generate that validation as well, I think I'm stuck doing things the way I've shown above. Please, prove me wrong!!
Pwninstein
Oh, WCF changes everything. If you are getting the data from a WCF service, then you are not working directly with the datacontext. When I did my WCF to ASP.Net application, the WCF service just became a data provider and I wrote view model classes that had data validation in them. Those classes retrieved the data and use IDataErrorInfo to pass the errors to the ASP.Net pages.
TheCodeMonk
A: 

The reason why your Validations are not being run when you set the DataContext is because WPF only runs validation when the source is updated with the value from the target (AKA, textbox is changed and the source is updated accordingly).

If you want to validate your data when you set the DataContext you'll have to iterate the logical tree, and for every element you want to run your validation for, you'll need to get its BindingExpression and then call the binding Expression UpdateSource method. That will force a validation.

The code to do something like that would be:

    private void ValidateData()
    {            
        //The XAML file defines a group of TextBox elements inside a Grid called grd
        foreach (UIElement uie in grd.Children)
        {
            if (uie.GetType() == typeof(TextBox))
            {
                ((TextBox)uie).GetBindingExpression(TextBox.TextProperty).UpdateSource();          
            }
        }                    
    }
Kiranu