Validating user input data is a crucial operation in data handling, especially
in CRUD (Create, Update, Delete) tasks.
There are numerous examples where
validation is essential. Numeric data may have to be validated for appropriate
ranges, alphabetic data may need to be validated for correctness, and so forth.
Let us now examine what provisions WPF has for data validation.
The Binding class in the WPF API has a property called ValidationRules which you
can use to associate your validation rules with Binding or MultiBinding objects.
To specify the value for this property, you can either derive from the
ValidationRule class or use one of the following built-in classes:
- ExceptionValidationRule
- DataErrorValidationRule.
The ExceptionValidationRule class catches any
exceptions that are thrown when you are trying to update the source whereas the
DataErrorValidationRule catches errors thrown if your source implements
IDataErrorInfo interface.
Instead of using the DataErrorValidationRule class, you can also set the
ValidateOnDataErrors property of the Binding object to true.
For now, let's just see a really basic example. We will include the following
code in our application to indicate that our validation rule is based on any
exceptions that may be thrown while updating the source.
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
</Binding.ValidationRules>
The application will consist of two TextBox controls , one accepting employee
name and the other accepting join date of the employee. The second textbox is
data bound to a column JoinDate in the Employee table. The example will raise
validation errors if the date format is not correct.
To start with, you will create the following table Employees in a database named
AuroraSystems.
Figure 1
Then, you will need to specify a database connection string in app.config.
App.config
<?xml
version="1.0"
encoding="utf-8"
?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add
name="DataDemo.Properties.Settings.EmployeeConnectionString"
connectionString="Data
Source=TestServer\EXPRESS;Initial Catalog=AuroraSystems;User ID=sa;Password=release"
providerName="System.Data.SqlClient"
/>
</connectionStrings>
</configuration>
Then you will create a typed DataSet object named EmpDataSet using the Data
Source Configuration Wizard.
Figure 2: Data Source Configuration Wizard
Figure 3: Data Source Configuration Wizard
Once this is done, you will add the following code to the MainWindow.xaml to
generate the two text boxes, button control, and validation rule.
MainWindow.xaml
<Window
x:Class="
DataDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="250"
Width="600">
<Grid
Height="215"
Width="485"
Background="LightGray">
<Grid.Resources>
<ControlTemplate
x:Key="ValidationTemplate">
<DockPanel
LastChildFill="True">
<TextBlock
DockPanel.Dock="Right"
Foreground="Red"
FontSize="12pt">
Invalid date!!!
</TextBlock>
<Border
BorderBrush="Red"
BorderThickness="1">
<AdornedElementPlaceholder
/>
</Border>
</DockPanel>
</ControlTemplate>
</Grid.Resources>
<TextBox
Name="txtJoinDate"
Margin="0,87,180,105"
Validation.ErrorTemplate="{StaticResource
ValidationTemplate}"
HorizontalAlignment="Right"
Width="140">
<TextBox.Text>
<Binding
Path="JoinDate"
UpdateSourceTrigger="LostFocus">
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button
Content="Submit"
Height="23"
HorizontalAlignment="Left"
Margin="230,116,0,0"
Name="button1"
VerticalAlignment="Top"
Width="75"
/>
<TextBlock
Height="23"
HorizontalAlignment="Left"
Margin="20,87,0,0"
Name="textBlock1"
Text="Enter
Join Date:"
VerticalAlignment="Top"
Width="77"
/>
<Label
Content="Enter
Employee Name:"
Height="28"
HorizontalAlignment="Left"
Margin="19,44,0,0"
Name="label1"
VerticalAlignment="Top"
/>
<TextBox
Height="23"
HorizontalAlignment="Left"
Margin="165,49,0,0"
Name="textBox1"
VerticalAlignment="Top"
Width="140"
/>
</Grid>
</Window>
Then, in the code-behind of MainWindow.xaml, you will add the following code:
public partial
class MainWindow
: Window
{
private
DateTime _JoinDate;
public MainWindow()
{
InitializeComponent();
EmpDataSet ds
= new EmpDataSet();
EmpDataSetTableAdapters.EmployeesTableAdapter eta =
new
EmpDataSetTableAdapters.EmployeesTableAdapter();
eta.Fill(ds.Employees);
txtJoinDate.DataContext = ds.Employees.DefaultView;
}
public DateTime
JoinDate
{
get {
return _JoinDate; }
set
{
try
{
MessageBox.Show(value.ToShortDateString());
}
catch (Exception
ex)
{
throw new
ApplicationException("Date
format not right");
}
_JoinDate = value;
}
}
}
The above code sets the DataContext of the text box to the Employees table. In
the property for JoinDate, we attempt to convert the entered date into ShortDate
format. If the date is entered in an incorrect format such as alphabetic format
or similar form, it will result in an exception, which in turn will result in a
validation error being thrown.
To customize the way the error is presented, WPF provides the
Validation.ErrorTemplate attached property on a custom control template. This
will help you to display errors in a better manner.
You can design a custom template as follows and assign it as a static resource
to the Validation.ErrorTemplate attached property.
<ControlTemplate
x:Key="ValidationTemplate">
<DockPanel
LastChildFill="True">
<TextBlock
DockPanel.Dock="Right"
Foreground="Red"
FontSize="12pt">
Invalid date!!!
</TextBlock>
<Border
BorderBrush="Red"
BorderThickness="1">
<AdornedElementPlaceholder
/>
</Border>
</DockPanel>
</ControlTemplate>
This basically creates a TextBlock which will show the appropriate message when
the error occurs. To make the TextBlock visually appealing, you can place it
inside a DockPanel and give it a border and some font styling.
On executing the application and entering some alphabetic data for date, an
error would be shown as seen in Figure 4.
Figure 4: Output