Search content within the blog

Monday, December 5, 2011

Validation Rules in WPF

WPF data binding model provides ability to validate user input. You can associate Validation Rule with your Binding as well with MultiBinding. Binding engine automatically checks whether any ValidationRule associated or not if yes then every time value passes to the source it will applies validation. Validation applies only when target value updates source value (i.e. with TwoWay or OneWayToSource binding modes).

To create validation rule you need to inherit ValidationRule class. This class is abstract class and has abstract method named Validate which returns ValidationResult type.

Below example explains how to associate validation rule to data binding.


<Window x:Class="WpfApplication1.ValidationRuleDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Validation Rule" Height="130" Width="280">
<Window.Resources>

<local:Employee x:Key="EmployeeInformation" />
<local:AgeRangeValidationRule x:Key="ageRangeValidation" />
<local:OnlyDigitsValidationRule x:Key="onlyDigitsValidation" />
<local:NameValidationRule x:Key="nameValidation" />

<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource=
{x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>

<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.20*"/>
<RowDefinition Height="0.20*" />
<RowDefinition Height="0" />
</Grid.RowDefinitions>

<TextBlock Text="Enter Name: " Grid.Column="0"
Grid.Row="0" Margin="3"/>
<TextBox Name="Name" Grid.Column="1"
Grid.Row="0" Height="30" Margin="3">
<TextBox.Text>
<Binding Source="{StaticResource EmployeeInformation}"
Path="Name">
<Binding.ValidationRules>
<local:NameValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="Enter Age: " Grid.Column="0"
Grid.Row="1" Margin="3"/>
<TextBox Name="Age" Grid.Column="1"
Grid.Row="1" Height="30" Margin="3">
<TextBox.Text>
<Binding Source="{StaticResource EmployeeInformation}"
Path="Age">
<Binding.ValidationRules>
<local:OnlyDigitsValidationRule />
<local:AgeRangeValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</Window>

Code Behind

public class Employee : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
private int age;
public int Age
{
get { return age; }
set { age = value; OnPropertyChanged("Age"); }
}

public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}

Validation Rule classes

public class NameValidationRule :ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
string name = value.ToString();
if (name.All(c=> char.IsLetter(c) || c== ' '))
return new ValidationResult(true, null);
return new ValidationResult(false, "Please enter only alphabets");
}
}

public class AgeRangeValidationRule: ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
int age = int.Parse(value.ToString());

if (age >= 18 && age <= 35)
{
return new ValidationResult(true, null);
}

return new ValidationResult(false,
"Please enter Age between 18 to 35");
}
}

public class OnlyDigitsValidationRule : ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
if (!value.ToString().All(c => char.IsDigit(c)))
return new ValidationResult(false,
"Please enter only digits");

return new ValidationResult(true, null);
}
}



No comments:

Post a Comment