tags:

views:

3900

answers:

5

Hi,

I am trying to validate the WPF form against an object. The validation fires when I type something in the textbox lose focus come back to the textbox and then erase whatever I have written. But if I just load the WPF application and tab off the textbox without writing and erasing anything from the textbox then it is not fired.

Here is the Customer.cs class:

public class Customer : IDataErrorInfo
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get
            {
                string result = null;

                if (columnName.Equals("FirstName"))
                {
                    // check for null or empty values 
                    if (String.IsNullOrEmpty(FirstName))
                    {
                        result = "FirstName cannot be null or empty"; 
                    }
                }

                else if (columnName.Equals("LastName"))
                {
                    if (String.IsNullOrEmpty(LastName))
                    {
                        result = "LastName cannot be null or empty"; 
                    }
                }

                return result; 

            }
        }


    }

And here is the WPF code:

 <TextBlock Grid.Row="1" Margin="10" Grid.Column="0">LastName</TextBlock>
        <TextBox Style="{StaticResource textBoxStyle}" Name="txtLastName" Margin="10" VerticalAlignment="Top" Grid.Row="1" Grid.Column="1">
          <Binding Source="{StaticResource CustomerKey}" Path="LastName" ValidatesOnExceptions="True" ValidatesOnDataErrors="True" UpdateSourceTrigger="LostFocus"/>         
        </TextBox>
+3  A: 

Unfortunately this is by design. WPF validation only fires if the value in the control has changed.

Unbelievable, but true. So far, WPF validation is the big proverbial pain - it's terrible.

One of the things you can do, however, is get the binding expression from the control's property and manually invoke the validations. It sucks, but it works.

cranley
A: 

Hi,

But then what is the purpose of the UpdateSourceTrigger="LostFocus" property.

azamsharp
A: 

I've gone through the same problem and found an ultra simple way to resolve this : in the Loaded event of your window, simply put txtLastName.Text = String.Empty. That's it!! Since the property of your object has changed (been set to an empty string), the validation's firing !

Thanks but that solution is not scalable and it will be hard to maintain on all the pages!
azamsharp
A: 

Take a look at the ValidatesOnTargetUpdated property of ValidationRule. It will validate when the data is first loaded. This is good if you're trying to catch empty or null fields.

You'd update your binding element like this:

<Binding 
    Source="{StaticResource CustomerKey}" 
    Path="LastName" 
    ValidatesOnExceptions="True" 
    ValidatesOnDataErrors="True" 
    UpdateSourceTrigger="LostFocus">
    <Binding.ValidationRules>
        <DataErrorValidationRule
            ValidatesOnTargetUpdated="True" />
    </Binding.ValidationRules>
</Binding>
w4g3n3r
If you check with reflector, you'll see that the 'ValidatesOnTargetUpdated' property is already set by DataErrorValidationRule to true. It calls an inherited constructor with a param which specifies this.So, adding the property assignments as shown won't make any difference.Good thought though - I've been trying to fix a similar problem and this did initially look promising.
Phil
+4  A: 

If you're not adverse to putting a bit of logic in your code behind, you can handle the actual LostFocus event with something like this:

.xaml

<TextBox LostFocus="TextBox_LostFocus" ....


.xaml.cs

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
     ((Control)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
Bermo