Search code examples
c#wpfidataerrorinfovalidationrules

How to validate data in WPF and set default value?


I'm trying to perform a validation property. We have a nullable property called:

    public int? Number
    {
        get { return _number; }
        set
        {
            if (_number != value)
            {
                _number = value;
                RaisePropertyChanged("Number");
            }
        }
    }

And this property is bound to a textbox. I only want to validate this two escenarios:

  • Imagine that the user left the textbox empty (textbox.text=""), so Number property must receive null value (instead "" ).
  • And if the user inputs "2b", Number property must have a null value (because is an error), but the textbox must still say "2b".

I guess IDataNotifyError and ValidationRules is not working for this. How can I resolve these situations?

EDIT: I'm using also a ValidationRule to show a custom message when the user inputs an incorrect format. But when this happens, does not fire the property to null. And if a put true in that error, it fired, but does not show any error message.

                 <TextBox.Text>
                    <Binding Path="Number" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True" NotifyOnValidationError="True" Converter="{x:Static c:IntConverter.Default}" >
                        <Binding.ValidationRules>
                                <r:NumericValidation />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>

The validation rule

public class NumericValidation : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        int? response;
        bool noIllegalChars = TryParseStruct<int>(value.ToString(), out response);

        if (noIllegalChars == false)
        {
            return new ValidationResult(false, "Input is not in a correct format.");
        }
        else
        {
            return new ValidationResult(true, null);
        }
    }

    ...
}

Solution

  • Try following converter:

    public class IntConverter : IValueConverter
    {
        public object Convert(object value,
                              Type targetType,
                              object parameter,
                              CultureInfo culture)
        {
            if (value is int?)
            {
                int? intValue = (int?)value;
                if (intValue.HasValue)
                {
                    return intValue.Value.ToString();
                }
            }
    
            return Binding.DoNothing;
        }
    
        public object ConvertBack(object value,
                                  Type targetType,
                                  object parameter,
                                  CultureInfo culture)
        {
            if(value is string)
            {
                int number;
                if (Int32.TryParse((string)value, out number))
                {
                    return number;
                }
            }
    
            return null;
        }
    }