Welcome to MSDN Blogs Sign in | Join | Help

Data Validation in Silverlight DataGrid

One of the features added to datagrid in Silverlight 3 Beta is Validation.  This can be done

-          Once we modify the content of a particular cell (cell validation)

-          Once we modify the content of a particular datagrid row (would like to commit changes to row) (Row Validation)

In this blog, I will try to give an intro both cell validation and row validation by using examples.

 

Cell Validation

Cell Validation can be done in two ways

-          Raising ValidationException in the property setter

-          Using ValidationAttributes and calling ValidateProperty in property setter

Cell Validation by throwing ValidationException in the property setter

In order to understand this concept, let’s consider that our datagrid is populated with a collection of Employee (with the following properties) objects  on which we want to do Cell Validation

        public String firstName;

        public String lastName;

        public int age;

        public String phone;

        public String city;

        public String state;

The validations that we want to do on these properties are

-          Firstname, lastname,  phone, city, state should not be null or empty

-          Age has to be in the range  18 to 50

We define validation rules for these properties (in the setter properties) in the following way.  The ValidationException (belonging to System.ComponentModel.DataAnnotations ) thrown is displayed as Cell Validation Error.

        public string LastName

        {

            get { return lastName; }

            set

            {

                if (value != lastName)

                {

                    if (value == null || value == string.Empty)

                    {

                        throw new ValidationException("Last Name cannot be empty");

                    }

                    lastName = value;

                    NotifyPropertyChanged("LastName");

                }

            }

        }

 cellvalidation1

        public int Age

        {

            get { return age; }

            set

            {

                if (value != age)

                {

                    if (value < 18 || value > 50 )

                    {

                        throw new ValidationException("Age should be between 18 and 50");

                    }

                    age = value;

                    NotifyPropertyChanged("Age");

                }

            }

        }

 cellvalidation2

Using Validation Attributes and calling ValidateProperty in property setter

The properties on which we want to do validation are decorated by validation attributes and we call the validationobject.validateproperty method in the setter of the property.  This tells the validator to verify on the decorated validation attribute when validateProperty is called. 

In the following code snippet,  the Required, Range and RegularExpression validation attributes are used.  The image below them shows the validation error when a validation rule is not met

        [Required]

        public string FirstName

        {

            get { return firstName; }

            set

            {

                if (value != firstName)

                {

                    Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "FirstName" });

                    firstName = value;

                    NotifyPropertyChanged("FirstName");

                }

            }

        }

 cellvalidation3

 

        [Required]

        [Range(18,50)]

        public int Age

        {

            get { return age; }

            set

            {

                if (value != age)

                {

                    Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Age" });

                    age = value;

                    NotifyPropertyChanged("Age");

                }

            }

        }

cellvalidation4 

 

        [Required]

        [RegularExpression("\\d{3}[-]\\d{3}[-]\\d{4}")] // (e.g - "999-999-1234")

        public string Phone

        {

            get { return phone; }

            set

            {

                if (value != phone)

                {

                    Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Phone" });

                    phone = value;

                    NotifyPropertyChanged("Phone");

                }

            }

        }

cellvalidation5 

Row Validation

In addition to doing validation when we edit a particular cell, we can perform validation when we commit a particular row or entity in the datagrid.  In order to do this,we decorate our BusinessObject class with the CustomValidation attribute that specifies the Validation class and the method that are used for validation. The row validation errors are shown at the bottom of the data grid in a error listbox.  Clicking on an error in the listbox focuses on the cell that that has validation error. Resolving the validation error dynamically removes the error from the listbox.

In addition to specifying the CustomValidation attribute on the business object, we can also use the validation attributes on the Properties to show invalid entries as Row Validation errors.

        [Required]

        public string FirstName

        {

            get { return firstName; }

            set

            {

                if (value != firstName)

                {

                    firstName = value;

                    NotifyPropertyChanged("FirstName");

                }

            }

        }

I will use the Employee class with the following properties as an example.  Note that I also show the decorated validation attributes on the properties of Employee just for demo purpose (In actuality the property definition looks similar to the above).

        [Required]

        public string FirstName

 

        [Required]

        public string LastName

 

        [Required]

        public DateTime? BirthDate

 

        [Required]

        [Range(18,50)]

        public int? Age

 

        [Required]

        public String City

 

        [Required]

        public String State

 

        [Required]

        [RegularExpression("\\d{3}[-]\\d{3}[-]\\d{4}")] // (e.g - "999-999-1234")

        public string Phone

 

Please note that we are not explicity calling the Validator.ValidateObject method or throwing ValidationExceptions in the setter for invalid values (Doing so will show cell validation errors).

The business object Employee class is decorated with the following customvalidation attributes

    [CustomValidation(typeof(EmployeeValidator), "IsValidBirthDay")]

    [CustomValidation(typeof(EmployeeValidator), "IsValidBirthDayAge")]

    public class Employee : INotifyPropertyChanged

The EmployeeValidator Class is static and we define validation methods inside it.  The class looks like below for this particular example.

    public static class EmployeeValidator

    {

        public static bool IsValidBirthDay(object employeeObject, ValidationContext context, out ValidationResult validationResult)

        {

            validationResult = null;

            Employee employee = employeeObject as Employee;

            DateTime date = employee.BirthDate.Value;

            int dateComparison = date.CompareTo(DateTime.Today);

            if (dateComparison > 1)

            {

                List<string> properties = new List<string>() { "BirthDate" };

                validationResult = new ValidationResult("Birthday cannot be further than today!", properties);

            }

 

            return !(dateComparison > 1);

        }

 

        public static bool IsValidBirthDayAge(object employeeObject, ValidationContext context, out ValidationResult validationResult)

        {

            validationResult = null;

            Employee employee = employeeObject as Employee;

            DateTime date = employee.BirthDate.Value;

            int age = DateTime.Today.Year - date.Year;

            if (age != employee.Age)

            {

                List<string> properties = new List<string>() { "Age", "BirthDate" };

                validationResult = new ValidationResult("Age does not match with Birthday! Your age should be " + age, properties);

            }

            return (age == employee.Age);

        } 

    }

If you observe the IsValidBirthDay validation method above, this checks if the propertry “Birthdate” is not further from today.     In the following code snippet

List<string> properties = new List<string>() { "BirthDate" };

                validationResult = new ValidationResult("Birthday cannot be further than today!", properties);

 

rowvalidation1

we tell the validator that in this validationmethod, we are checking the property BirthDate only.  We can check more than one property and associate them with a validation error.  This is done for example in the IsValidBirthDayAge  where the (Age,BirthDate) properties are checked for which the code which does this looks like below.    When we click on the validation error in the listbox, we toggle between the properties (Age, BirthDate).

                List<string> properties = new List<string>() { "Age", "BirthDate" };

                validationResult = new ValidationResult("Age does not match with Birthday! Your age should be " + age, properties);

rowvalidation2

As you can see, developers can use these validation features that datagrid supports to develop compeling apps.

Published Sunday, March 22, 2009 1:39 PM by nagasr

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# infoblog &raquo; Data Validation in Silverlight DataGrid

Monday, April 06, 2009 9:02 PM by Satish

# re: Data Validation in Silverlight DataGrid

Hi Jeneate, please let me know the problem you are facing.  

Monday, April 06, 2009 9:03 PM by Satish

# re: Data Validation in Silverlight DataGrid

Hi Jeneate, please let me know the problem you are facing.  

Thursday, April 09, 2009 12:49 AM by Method ~ of ~ failed by Tim Heuer

# Grouping data in Silverlight DataGrid

Grouping data in Silverlight DataGrid

Thursday, April 09, 2009 1:05 AM by Microsoft Weblogs

# Grouping data in Silverlight DataGrid

I got this question on how do you add grouping to the DataGrid in Silverlight without using the RIA Services

Friday, May 15, 2009 7:15 PM by samcov

# re: Data Validation in Silverlight DataGrid

Why don't you attach the project to this article?

Tuesday, July 14, 2009 9:13 AM by Sagar Date

# re: Data Validation in Silverlight DataGrid

Hi Satish,

Nice article,

All the ways of validations are collated

It will be gerat if you add the code along with

For the third method you have suggested 'Row Validation' Can you please add the code required to display the validation summery and also xamal code for same.

I tried with first and second approach it works fine.But raising the exception on validation is not digesting thing. Can you give more details on third method.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker