Converter and Validator in one place

15 באפריל 2007

תגיות: ,
תגובה אחת

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/converter-and-validator-in-one-place/]


Today, Doug asked about strange behavior with Binding Validation, while using custom converters. Follow XAML and C# code for his question:


 



<StackPanel>
    <StackPanel.DataContext>
      <x:Array Type="s:Int32" xmlns:s="clr-namespace:System;assembly=mscorlib">
        <s:Int32>0</s:Int32>
        <s:Int32>1</s:Int32>
      </x:Array>
    </StackPanel.DataContext>
    <TextBox Margin="3">
      <TextBox.Text>
        <Binding Path="[0]">
          <Binding.ValidationRules>
            <ExceptionValidationRule />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
    <TextBox Margin="3">
      <TextBox.Text>
        <Binding Path="[1]">
          <Binding.Converter>
            <local:MyInt32Converter xmlns:local="clr-namespace:myNamespace" />
          </Binding.Converter>
          <Binding.ValidationRules>
            <ExceptionValidationRule />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
  </StackPanel>
 
 

public class MyInt32Converter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            return value.ToString();
        }
 
        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            return Int32.Parse(value.ToString());
        }
 
    }

Compile and run it. Then change value to something bad (e.g. "aaa") in first textbox – the validator will be fired and we'll get red border in our textbox. Then change the value of the second textbox – you'll get exception. Why this?


The answer is really simple – the sequence of binding is straight forward – get,convert,validate result. So, how to get this work with custom converters? Just convert it to validator. Following code in this converter will check and validate input value first, then, if the input is valid, convert and return results.


 



    [ValueConversion(typeof(String), typeof(Int32))]
    public class MyInt32Converter : ValidationRule, IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            return value.ToString();
        }
 
        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if (this.Validate(value, culture) == ValidationResult.ValidResult)
            {
                return Int32.Parse(value.ToString());
            }
            return value;
        }
 
 
 
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            int i=0;
            return new ValidationResult(Int32.TryParse(value.ToString(),out i),"The string is in incorrect format");
        }
    }

Have a nice day.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

תגובה אחת

  1. decPL5 בפברואר 2008 ב 18:17

    There's no need to make it a ValidationRule – your Validate function is only called in your code, not by the Binding (unless I'm missing something – even if I am, this is doing validation one time too many).
    Just checking the value in Convert(/Back) functions is enough

    הגב