OpenLightGroup Blog

rss

Blogs from OpenLightGroup.net


Basic Silverlight View Model Validation

image

Live Sample: http://silverlight.adefwebserver.com/RIATasks2ABValidation/RIATasksWeb/

There are many types of Silverlight Validation. This covers the most basic type, validating that the data entered matches the underlying type. In this example we will validate a Date Field.

We will start of with the Creating Multiple Dynamic View Models using the Tab Control project.

 

image

 

We add a DueDate field to the Tasks table that is nullable.

 

image

 

We will alter the View so that it has a “Due Date” field and permits these operations:

  • Indicates when a valid date is not entered
  • Allows you to not enter a date at all

 

The Validation Handler “Helper Class”

We will first add a helper class created by John Papa:

using System;
using System.Collections.Generic;
using System.Windows.Input;
 
// From http://johnpapa.net/silverlight/enabling-validation-in-silverlight-4-with-idataerrorinfo/
 
namespace RIATasks
{
    public class ValidationHandler
    {
        private Dictionary<string, string> BrokenRules { get; set; }
        public ValidationHandler()
        {
            BrokenRules = new Dictionary<string, string>();
        }
 
        public string this[string property]
        {
            get
            {
                return this.BrokenRules[property];
            }
        }
 
        public bool BrokenRuleExists(string property)
        {
            return BrokenRules.ContainsKey(property);
        }
 
        public bool ValidateRule(string property, string message, Func<bool> ruleCheck)
        {
            if (!ruleCheck())
            {
                this.BrokenRules.Add(property, message);
                return false;
            }
            else
            {
                RemoveBrokenRule(property);
                return true;
            }
        }
 
        public void RemoveBrokenRule(string property)
        {
            if (this.BrokenRules.ContainsKey(property))
            {
                this.BrokenRules.Remove(property);
            }
        }
    }
}

 

 

Here are the steps to consume the class:

 

image

  • Specify the IDataErrorInfo interface
  • Instantiate the ValidationHandler class

 

Implement the IDataErrorInfo with code that will use the ValidationHandler

 

        #region Error Validation
        public string Error
        {
            get { return null; }
        }
 
        public string this[string columnName]
        {
            get
            {
                if (this.validationHandler.BrokenRuleExists(columnName))
                {
                    return this.validationHandler[columnName];
                }
                else
                {
                    return null;
                }
            }
        }
        #endregion

 

Create a property for DueDate that is a string, it will display, and save any values to the DueDate property that is in the Task object (I got this technique from Richard Waddell).

The reason we do this is so that the user can enter anything in the View and the binding will still work. If we set the binding to bind directly to the DueDate property that is in the Task object, we would not have access to the values if the user does not put in a valid date.

This would make it hard to provide the user a smooth “experience” for fixing their errors.

 

        #region DueDate
        private string _DueDate = null;
        public string DueDate
        {
            get
            {
                // The first time this is called DueDate will be null
                // set DueDate to _CurrentTask.DueDate
                if (_DueDate == null && (_CurrentTask.DueDate.HasValue))
                {
                    return _CurrentTask.DueDate.Value.ToShortDateString();
                }
                else
                {
                    // In all other situations return DueDate
                    return _DueDate;
                }
            }
            set
            {
                if (_DueDate == value)
                {
                    return;
                }
 
                var dateOut = new DateTime();
                bool IsADate = (DateTime.TryParse(value, out dateOut) == true);
 
                // If value is not empty it must be a date
                bool valid = validationHandler.ValidateRule(
                    "DueDate", "Must be a valid date", 
                    () => ((value == "") || (value != "" && IsADate)));
 
                if (valid)
                {
                    // Assign value to CurrentTask.DueDate
                    if (IsADate)
                    {
                        CurrentTask.DueDate = Convert.ToDateTime(value);
                    }
                    else
                    {
                        CurrentTask.DueDate = null;
                    }
                }
 
                _DueDate = value;
                this.NotifyPropertyChanged("DueDate");
            }
        }
        #endregion

 

 image

The last step, to make it show the red box around the TextBox when there is an error, is to add ValidatesOnDataErrors=True to the binding on the TextBox.

 

Download

You can download the code at this link:

http://silverlight.adefwebserver.com/RIATasks2ABValidation/RIATasks2ABValidation.zip





Comments are closed.