Data Validation in WPF

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.

DataValWPF1.bmp

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.

DataValWPF2.bmp

Figure 2: Data Source Configuration Wizard

DataValWPF3.bmp

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.

DataValWPF4.bmp

Figure 4: Output