Thursday 20 September 2012


Understanding Validation in Silverlight


Hi Friends,

In this article i will tell you 4 types of validations in silverlight in brief. 

There are 4 types of validation in silverlight 4.0.



1.The basic validation
Validation in Silverlight can get very complex and easy. The DataGrid control is the only control that does data validation automatically, but often you want to validate your own entry form. Values a user may enter in this form can be restricted by the customer and have to fit an exact fit to a list of requirements or you just want to prevent problems when saving the data to the database. Showing a message to the user when a value is entered is pretty straight forward as I’ll show you in the following example.







This (default) Silverlight textbox is data-bound to a simple data class. It has to be bound in “Two-way” mode to be sure the source value is updated when the target value changes. The INotifyPropertyChanged interface must be implemented by the data class to get the notification system to work. When the property changes a simple check is performed and when it doesn’t match some criteria anValidationException is thrown. The ValidatesOnExceptions binding attribute is set to True to tell the textbox it should handle the thrown ValidationException. Let’s have a look at some code now.
The xaml should contain something like below. The most important part is inside the binding. In this case the Text property is bound to the “Name” property in TwoWay mode. It is also told to validate on exceptions. This property is false by default.

<StackPanel Orientation="Horizontal">
<TextBox Width="150"
x:Name="Name"
              Text="{Binding Path=Name,
Mode=TwoWay,
ValidatesOnExceptions=True}"/>
<TextBlock Text="Name"/>
</StackPanel>


The data class in this first example is a very simplified person class with only one property: string Name. The INotifyPropertyChanged interface is implemented and the PropertyChanged event is fired when the Name property changes. When the property changes a check is performed to see if the new string is null or empty. If this is the case a ValidationException is thrown explaining that the entered value is invalid.

public class PersonData:INotifyPropertyChanged
{
private string _name;
public string Name
  {
get { return _name; }
set
    {
if (_name != value)
      {
if(string.IsNullOrEmpty(value))
throw new ValidationException("Name is required");
        _name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
      }
    }
  }
public event PropertyChangedEventHandlerPropertyChanged=delegate { };
}


The last thing that has to be done is letting binding an instance of the PersonData class to the
DataContext of the control. This is done in the code behind file.
public partial class Demo1 : UserControl
{
public Demo1()
  {
InitializeComponent();
this.DataContext = new PersonData() {Name = "Johnny Walker"};
  }
}


Error Summary
In many cases you would have more than one entry control. A summary of errors would be nice in such case. With a few changes to the xaml an error summary, like below, can be added.


 




First, add a namespace to the xaml so the control can be used. Add the following line to the header of the .xaml file.
xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"

Next, add the control to the layout. To get the result as in the image showed earlier, add the control right above the StackPanel from the first example. It’s got a small margin to separate it from the textbox a little.


<Controls:ValidationSummary Margin="8"/>


The ValidationSummary control has to be notified that anValidationException occurred. This can be done with a small change to the xaml too. Add the NotifyOnValidationError to the binding expression. By default this value is set to false, so nothing would be notified. Set the property to true to get it to work.

<TextBox Width="150"
x:Name="Name"
    Text="{Binding Name,
                   Mode=TwoWay,
ValidatesOnExceptions=True,
NotifyOnValidationError=True}"/>


2.Data annotation
Validating data in the setter is one option, but not my personal favorite. It’s the easiest way if you have a single required value you want to check, but often you want to validate more. Besides, I don’t consider it best practice to write logic in setters. The way used by frameworks like WCF Ria Services is the use of attributes on the properties. Instead of throwing exceptions you have to call the static method ValidateProperty on the Validator class. This call stays always the same for a particular property, not even when you change the attributes on the property.
To mark a property “Required” you can use the RequiredAttribute. This is what the Name property is going to look like:

[Required]
public string Name
{
get { return _name; }
set
  {
if (_name != value)
    {
Validator.ValidateProperty(value,
newValidationContext(this, null, null){ MemberName = "Name" });
      _name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
    }
  }
}


The ValidateProperty method takes the new value for the property and an instance of ValidationContext. The properties passed to the constructor of the ValidationContextclass are very straight forward. This part is the same every time. The only thing that changes is the MemberName property of the ValidationContext. Property has to hold the name of the property you want to validate. It’s the same value you provide the PropertyChangedEventArgs with.
The System.ComponentModel.DataAnnotation contains eight different validation attributes including a base class to create your own.
They are:
Specifies that a value must be provided.
The provide value must fall in the specified range.
Validates is the value matches the regular expression.
Checks if the number of characters in a string falls between a minimum and maximum amount.
Use a custom method to validate the value.
Specify a data type using an enum or a custom data type.
Makes sure the value is found in aenum.
A base class for custom validation attributes
All of these will ensure that an validation exception is thrown, except the DataTypeAttribute. This attribute is used to provide some additional information about the property. You can use this information in your own code.

[Required]
[Range(0,125,ErrorMessage = "Value is not a valid age")]
publicint Age
{


It’s no problem to stack different validation attributes together. For example, when an Age is required and must fall in the range from 0 to 125:

[Required, StringLength(255,MinimumLength = 3)]
public string Name
{


Or in one row like this, for a required Name with at least 3 characters and a maximum of 255:

3. IDataErrorInfo
I have used ‘IDataErrorInfo’ interface which is newly provided in Silverlight 4.0 under System.ComponentModelnamepsace. This interface needs to be implemented by the data entity class which helps in defining custom validations for data to be entered using Silverlight 4.0 UI controls.

The IDataErrorInfo interface came with Silverlight 4. If we want implement validation with this interface we should implement it in our ViewModel (one property and one method). Usually developers write own class handler, which store validation errors)

publicclassEmployee : INotifyPropertyChanged, IDataErrorInfo
{
    int _EmpNo;

    publicintEmpNo
    {
        get
        {
            return _EmpNo;
        }
        set
        {
            _EmpNo = value;
            ChangeValue("EmpNo");
        }
    }
    string _EmpName;

    publicstringEmpName
    {
        get
        {
            return _EmpName;
        }
        set
        {
            _EmpName = value;
            ChangeValue("EmpName");
        }
    }
publiceventPropertyChangedEventHandlerPropertyChanged;

    publicvoidChangeValue(stringPropName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, newPropertyChangedEventArgs(PropName));
        }
    }

    string err;
    publicstring Error
    {
        get { return err; }
    }

    publicstringthis[stringcolumnName]
    {
        get
        {
            stringmsg = null;
            if (columnName == "EmpNo")
            {
                if (EmpNo<= 0 || EmpNo.ToString().Length > 5)
                {
                    msg = "EmpNo must not be Negative or Lenght must not be more than 5.";
                }
            }

            if (columnName == "EmpName")
            {
                if (EmpName.Equals(string.Empty))
                {
                    msg = "EmpName is must,Please enter Correct Value.";
                }
            }
returnmsg;
        }
    }
}

In XAML
<TextBoxGrid.Row="1"Height="23"
                 HorizontalAlignment="Left"Margin="148,21,0,0"
                 Name="txtEno"
                 Text="{Binding Path=EmpNo,Mode=TwoWay,ValidatesOnDataErrors=True}"
                 VerticalAlignment="Top"Width="120"/>
        <TextBoxGrid.Row="1"Height="23"HorizontalAlignment="Left"
                 Margin="148,66,0,0"Name="txtEname"
                 Text="{Binding Path=EmpName,Mode=TwoWay,ValidatesOnDataErrors=True}"
                 VerticalAlignment="Top"Width="120"
                 />
4. INotifyDataErrorInfo

The INotifyDataErrorInfointerface came with Silverlight 4 too. The main advantage of this interface you can do synchronous (like in previous samples) and asynchronous validation too. You can wait validation from server, and only after that tell to interface that all ok or some validation error occurred. I like this way of validation more than other


publicIEnumerableGetErrors(stringpropertyName)
    {
if (_errorMessages.ContainsKey(propertyName)) 
return _errorMessages[propertyName];
 
returnnewstring[0];
    }
 
publicboolHasErrors
    {
get { return _errorMessages.Count> 0; }
    }



Happy Programming ! !
If you have any query mail me to Sujeet.bhujbal@gmail.com     
Regards
Sujeet Bhujbal
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------