Search code examples
c#wpfvalidationidataerrorinfo

IDataErrorInfo : Not validating input


I have a user control which contains a textbox. I have a class called Person which implements IDataErrorInfo interface:

class Person : IDataErrorInfo
{
private bool hasErrors = false;
#region IDataErrorInfo Members

        public string Error
        {            
            get 
            {
                string error = null;
                if (hasErrors)
                {
                    error = "xxThe form contains one or more validation errors";
                }
                return error;
            }
        }

        public string this[string columnName]
        {
            get 
            {
                return DoValidation(columnName);
            }
        }
        #endregion
}

Now the usercontrol exposes a method called SetSource through which the code sets the binding:

public partial class TxtUserControl : UserControl 
    {          
        private Binding _binding;

        public void SetSource(string path,Object source)
        {
            _binding = new Binding(path);
            _binding.Source = source;
            ValidationRule rule;
            rule = new DataErrorValidationRule();
            rule.ValidatesOnTargetUpdated = true;            
            _binding.ValidationRules.Add(rule);
            _binding.ValidatesOnDataErrors = true;
            _binding.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
            _binding.NotifyOnValidationError = true;            
            _binding.ValidatesOnExceptions = true;
            txtNumeric.SetBinding(TextBox.TextProperty, _binding);                
        }
...
}

The WPF window that includes the user control has the following code:

public SampleWindow()
    {
        person= new Person();
        person.Age = new Age();
        person.Age.Value = 28;

        numericAdmins.SetSource("Age.Value", person);
    }
    private void btnOk_Click(object sender, RoutedEventArgs e)
    {         

        if(!String.IsNullOrEmpty(person.Error))
        {
            MessageBox.Show("Error: "+person.Error);
        }
    }

Given this code, the binding is working fine, but the validation never gets triggered. Whats wrong with this code?


Solution

  • Your Age class will need to implement IDataErrorInfo. Your Person class won't be asked to validate the Age's properties.

    If that is not an option, I wrote a validation system for WPF that is extensible enough to support this. The URL is here:

    In the ZIP is a word document describing it.

    Edit: here's one way age could implement IDataErrorInfo without being too smart:

    class Constraint 
    {
        public string Message { get; set; }
        public Func<bool> Validate;
        public string Name { get; set; }
    }
    
    class Age : IDataErrorInfo
    {
        private readonly List<Constraint> _constraints = new List<Constraint>();
    
        public string this[string columnName]
        {
            get 
            {
                var constraint = _constrains.Where(c => c.Name == columnName).FirstOrDefault();
                if (constraint != null)
                {
                    if (!constraint.Validate())
                    {
                        return constraint.Message;
                    }
                }
                return string.Empty;
            }
        }
    }
    
    class Person
    {
        private Age _age;
    
        public Person() 
        {
            _age = new Age(
                new Constraint("Value", "Value must be greater than 28", () => Age > 28);
        }
    }
    

    Also see this link:

    http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx