2

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);
        }
    }

    ...
}
Darf Zon
  • 6,268
  • 20
  • 90
  • 149
  • How do ValidationRules not work in this situation? – Kai G Jan 25 '12 at 05:57
  • @Kai Because Validation is just for advise the user some constraints of validation. I mean, it does not treat with logic as at this case. – Darf Zon Jan 25 '12 at 06:00

3 Answers3

3

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;
    }
}
Amit
  • 929
  • 8
  • 27
  • Wow, this is beautiful, I have no idea about the converters. Everything is okay, but I realized that when you input "8b", the program thinks is okay, and does not update the property to null at this moment. Do you know how to fix it? – Darf Zon Jan 25 '12 at 06:05
  • What it set to the property in case of "8b". Try putting break point in converter's ConvertBack method and see what it returns. – Amit Jan 25 '12 at 06:27
  • Well, I've gotta tell you that I'm using also a validation rule. This just shows a custom message when input an incorrect format, and I realized when ValidationResults is false, don't fire the property. – Darf Zon Jan 25 '12 at 06:30
  • Binding will not update source if your Validation Rule return false. It is better to implement IDataErrorInfo in your view model. – Amit Jan 25 '12 at 06:44
  • I don't understand, in my view model I don't have a string property for Number. – Darf Zon Jan 25 '12 at 18:26
2

You can use converter and manipulate the values before they are assigned to underlying property.

sanguine
  • 281
  • 1
  • 6
1

Use @Amit's converter and then to get the error use IDataErrorInfo with the following code:

public string this[string columnName]
{
    get
    {
        if (columnName == "Number")
        {
            if (Number == null) return "Invalid number";
        }

        return null;
    }
}

Or you could do it with your ValidationRule but you would need to change its ValidationStep property. Your validation is currently being fired at the default time RawProposedValue, i.e. before the converter is kicking in.

Kai G
  • 3,371
  • 3
  • 26
  • 30
  • @Armit I don't understand why Number == null is an error, I said because Number is a Nullable datatype (int?) – Darf Zon Jan 25 '12 at 18:23
  • Armit's converter will convert invalid numbers to null. After that, IDataErrorInfo's method will be called to validate. Therefore a null value will mean an invalid number has been entered. – Kai G Jan 27 '12 at 03:52