DataAnnotations Validation Attributes in Windows Forms

In this post, I’ll show how to use Data Annotation Validation attributes to perform validation in a Windows Forms Application. Data Annotation Validation attributes enable you to perform model validation simply by decorating class properties with validation attributes such as the Required, StringLength, RegularExpression, Range, Url, etc.

Introducing IDataErrorInfo

To show validation errors in Windows Forms, the frame work has an ErrorProvider component. The framework also supports showing error in DataGridView. To be able to show model errors in DataGridView or showing errors using ErrorProvider the model which you are using in data binding should implement IDataErrorInfo. For example DataRowView which is the main model which is usually used in classic ADO.NET applications, has implemented IDataErrorInfo.

Here is the interface definition:

public interface IDataErrorInfo
{
    string this[string columnName] { get; }
    string Error { get; }
}

The interface contains two properties:

  • Error: Gets an error message indicating what is wrong with this object.
  • Item[String]: Gets the error message for the property with the given name.

Implementing IDataErrorInfo using Data Annotations Validation Attributes

To bring validation attributes support to our model classes, we need to implement IDataErrorInfo. There is a Validator class in System.ComponentModel.DataAnnotations.dll which has a couple of methods which allows us to validate an object or a property of an object using validation attributes:

using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
public class BaseModel : IDataErrorInfo
{
    [Browsable(false)]
    public string this[string property]
    {
        get
        {
            var propertyDescriptor = TypeDescriptor.GetProperties(this)[property];
            if (propertyDescriptor == null)
                return string.Empty;

            var results = new List<ValidationResult>();
            var result = Validator.TryValidateProperty(
                                      propertyDescriptor.GetValue(this),
                                      new ValidationContext(this, null, null)
                                      { MemberName = property },
                                      results);
            if (!result)
                return results.First().ErrorMessage;
            return string.Empty;
        }
    }

    [Browsable(false)]
    public string Error
    {
        get
        {
            var results = new List<ValidationResult>();
            var result = Validator.TryValidateObject(this,
                new ValidationContext(this, null, null), results, true);
            if (!result)
                return string.Join("\n", results.Select(x => x.ErrorMessage));
            else
                return null;
        }
    }
}

Example

Let’s create a sample model and decorate its properties with validation attributes:

public class SampleModel : BaseModel
{
    [Required]
    [Range(1, 100)]
    public int? Id { get; set; }

    [Required]
    [StringLength(10)]
    [RegularExpression("w+")]
    public string Name { get; set; }

    [Required]
    [StringLength(500, MinimumLength = 10)]
    public string Description { get; set; }

    [Required]
    [Range(1, 100000)]
    public int Price { get; set; }

    [Required]
    [Url]
    public string Url { get; set; }
}

Then if you setup data binding using to SampleModel using a BindingSource and use an ErrorProvider, then you can see error icon near the controls and if you hover on the error icon, you can see error message in tooltip:

validation-details

Also if you use a DataGridView, errors will be shown on cells and rows:

validation-grid

Download

You can clone or download the working example:

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *