Validation in WPF Using IDataErrorInfo Interface

In WPF we can do validation in several ways – using IDataErrorInfo , INotifyDataErrorInfo
Both of these Interfaces gives you the ability to provide visual feedback to the user without throwing exceptions. Validations are closely related to binding.

Namespace : System.ComponentModel

This article explains how you can validate the data entered by the user. IDataErrorInfo Interface gives you relatively easy and simple client side validations . Let us know something about IDataErrorInfo Interface. This Interface provides two properties. – Error and Item.

  • ‘Error’ – used to get a validation error message for the entire object. It’s Return type is string.
  • string Error { get; }
  • ‘Item’ (Indexer) – It is used to get specific error messages for specific property or column name. So the name of the property is used to retrieve the validation error message.
  • string this[
    string columnName
    ] { get; }

Note : Validation applies only when a value from the target is being used to update the source—in other words, when you’re using a TwoWay or OneWayToSource binding.

Example
Let us Demonstrate an example and let us validate User controls by using IDataErrorInfo.

Snapshot of Output
IDataErrorInfo

Create a class and name it – ViewModelEmployee.cs
Implement this class with IDataErrorInfo Interface

public class ViewModelEmployee : IDataErrorInfo
{
private string empId;
public string EmpId
{
get { return empId; }
set { empId = value; }
}

private string empName;
public string EmpName
{
get { return empName; }
set { empName = value; }
}

private string accountno;
public string AccountNo
{
get { return accountno; }
set { accountno = value; }
}
public string Error
{
get { throw new NotImplementedException(); }
}

public string this[string columnName]
{
get
{
string responseMessage = String.Empty;
switch (columnName)
{
case “EmpId”:
if (String.IsNullOrEmpty(this.EmpId))
{
responseMessage = “Please enter the Employee Id”;
}
else if (this.EmpId.Length < 5) {
responseMessage = “Employee Id must be greater then 5 characters”;
}
break;
case “EmpName”:
if (string.IsNullOrEmpty(this.EmpName))
{
responseMessage = “Please enter the Employee Name”;
}
break;
case “AccountNo”:
if (columnName.Equals(“AccountNo”))
{
int account;
if (string.IsNullOrEmpty(this.AccountNo))
{
responseMessage = “Please enter the valid Account Number”;
}
else if (!Int32.TryParse(this.AccountNo, out account))
{
responseMessage = “Account Number must be numeric digit”;
}
}
break;
};
return responseMessage;
}
}
}

In the above class I have created three properties – empId, empName, accountno. And provide defination to the two properties of the Interface.

Now let us open the xaml code and make the UI.

MainWindow.xaml

<Window x:Class=”IDataErrorInfo_Validation.MainWindow”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:vm=”clr-namespace:IDataErrorInfo_Validation”
Title=”IDataErrorInfo Demo” Height=”350″ Width=”525″ Background=”#98dafc” >

<Window.DataContext>
<vm:ViewModelEmployee></vm:ViewModelEmployee>
</Window.DataContext>

<Window.Resources>
<Style TargetType=”TextBox” >
<Setter Property=”Validation.ErrorTemplate” >
<Setter.Value>
<ControlTemplate >
<StackPanel Orientation=”Vertical”>
<DockPanel>
<Border BorderThickness=”1″ BorderBrush=”Red” DockPanel.Dock=”Left”>
<AdornedElementPlaceholder />
</Border>
<TextBlock Text=””/>
</DockPanel>
<TextBlock Foreground=”White” Background=”Green” FontWeight=”Bold”
Text=”{Binding Path=ErrorContent}” />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property=”Validation.HasError” Value=”true”>
<Setter Property=”ToolTip” Value=”{Binding RelativeSource={x:Static RelativeSource.Self}, Path=ErrorContent}” />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>

<Grid Margin=”30,30″ >
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”0.3*” />
<ColumnDefinition Width=”*” />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height=”*” />
<RowDefinition Height=”*” />
<RowDefinition Height=”*” />
<RowDefinition Height=”*” />
<RowDefinition Height=”*” />
</Grid.RowDefinitions>

<TextBlock Text=”IDataErrorInfo” FontSize=”25″ Grid.ColumnSpan=”2″ />

<TextBlock Text=”EmpId” Grid.Row=”1″ Grid.Column=”0″ />
<TextBox Grid.Row=”1″ Grid.Column=”1″ Width=”200″ Height=”30″
Text=”{Binding Path=EmpId,Mode=TwoWay,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}” />

<TextBlock Text=”EmpName” Grid.Row=”2″ Grid.Column=”0″ />
<TextBox Grid.Row=”2″ Grid.Column=”1″ Width=”200″ Height=”30″
Text=”{Binding Path=EmpName,Mode=TwoWay,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}” />

<TextBlock Text=”Account Number” Grid.Row=”3″ Grid.Column=”0″ />
<TextBox Grid.Row=”3″ Grid.Column=”1″ Width=”200″ Height=”30″
Text=”{Binding Path=AccountNo,Mode=TwoWay,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}” />

</Grid>
</Window>

Here in the UI we bind the user controls to the properties of an entity (ViewModelEmployee.cs in our case) which is implementing IDataErrorInfo Interface. And we have added the reference of the namespace of the viewmodel class in our xaml code. The validation errors are shown as tooltip as well as the visual error message. Its code is written in Window.Resources section targeting all the textboxes.

OUTPUT
IDataErrorInfo

Notice with each Input field we have set ValidatesOnDataErrors = True

Hope this article helps!! Comments and Suggestions are always welcome. Thank You