tags:

views:

683

answers:

2

I have TextBox which should only contain a valid integer. It’s validated using a custom ValidationRule. The problem I am experiencing is that when the TextBox.Text is invalid, say “3a”, and I type another “a”, then the TextBox’s attached property Validation.HasError changes from TRUE -> FALSE -> TRUE. My software reacts whenever the Validation.HasError is FALSE, but the TextBox.Text is “3a” at that point in time which is not desirable.

Here is how I see things: The TextBox.Text="3a" and Validation.HasError=TRUE. Now I type an additional “a” and the following happens. First the Validation process removes the existing ValidationError and raises a Validation.Error event with ValidationErrorEventArgs.Action=”Removed”. Now the Validation.HasError=FALSE. Straight afterwards the Validation process adds a new ValidationError and raises a Validation.Error event with ValidationErrorEventArgs.Action=”Added”. Now the Validation.HasError=TRUE again.

All I can do is react to Validation.Error events and then inspect the source object’s Validation.HasError attached property to see if it is true or false. Unfortunately the Validation.HasError returns false when the TextBox.Text=”3a” which is clearly not a valid integer.

Any ideas would be very helpful. Thanks :)

A: 

You should post your binding and validation code.

batzen
A: 

I have the same problem. Did anyone solve this issue? The side effect of this issue is when you have popup window, which is being displayed based on Validation.HasError value, it's blinking on every keypress and the UX is horrible. Changing the binding mode is not solution for me, I want to use UpdateSourceTrigger="PropertyChanged" in this case.

Here are the codes (DataContext is any object containing Text property implementing INotifyPropertyChanged interface):

Window1.xaml

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:WpfApplication1="clr-namespace:WpfApplication1" 
    Height="300"
    Width="300">
    <StackPanel>
        <TextBox Name="tbValue">
            <TextBox.Text>
                <Binding Path="Text" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <WpfApplication1:StringLengthValidationRule MinLength="2" MaxLength="10" />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Popup Name="errPopup" 
                PlacementTarget="{Binding ElementName=tbValue}"
                IsOpen="{Binding ElementName=tbValue, Path=(Validation.HasError), Mode=OneWay}">
            <Border Background="Beige" Padding="10">
                <TextBlock Text="{Binding ElementName=tbValue, Path=(Validation.Errors)[0].ErrorContent}" />
            </Border>
        </Popup>
    </StackPanel>
</Window>

StringLengthValidationRule.cs

namespace WpfApplication1
{
    using System.Globalization;
    using System.Windows.Controls;

    public class StringLengthValidationRule : ValidationRule
    {
        public int MinLength { get; set; }
        public int MaxLength { get; set; }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string val = value as string;

            if (string.IsNullOrEmpty(val) && this.MinLength > 0)
                return new ValidationResult(false, string.Format("Value must be at least {0} characters long.", this.MinLength));

            if (val == null)
                val = string.Empty;

            if (val.Length < this.MinLength)
                return new ValidationResult(false, string.Format("Value can be minimally {0} characters long.", this.MinLength));

            if (val.Length > this.MaxLength)
                return new ValidationResult(false, string.Format("Value can be maximally {0} characters long.", this.MaxLength));

            return new ValidationResult(true, null);
        }
    }
}
bretik