Click here to Skip to main content
15,887,746 members
Articles / Desktop Programming / WPF
Tip/Trick

WPF Validation - Using IDataErrorInfo

Rate me:
Please Sign up or sign in to vote.
4.87/5 (12 votes)
31 Dec 2014CPOL4 min read 75.4K   1.8K   23   10
Focus on WPF Novice to easily understand Data Validation using IDataErrorInfo interface

Introduction

I do not want to waste time to speak up my things, how I faced hard times when this concept was given to me to apply in my project.

Now I am really satisfied with myself because it induced me to write up this topic. This tip would be more useful to a novice in WPF.

Basically, we can achieve data validation in two ways:

Now, I would like to give you the idea in Part 1 sample project implementation. We will see Part 2 implementation in the upcoming post.

Part 1 - Using the Code

Step 1

Create a project (WpfValidation.csproj), and then create a class file named as “Customer.cs”.

Step 2

In Customer.cs file, create the “Name” property as given below. If you want to use some logic in name validation, then use one private name backing field along with public property. Here, I do not want to have any additional logic for Name property. So I simply use Public property only.

C#
public string Name
{    
   get; set;   
}

Step 3

Implement “IDataErrorInfo” interface in Customer.cs file.

Import this namespace “using System.ComponentModel”.

This interface gives us two properties, those are Error and this.

Change those two interfaces as below:

C#
public string Error
{
    get { return null; }
}

public string this[string columnName]
{
    get
    {
        string result = string.Empty;
        if (columnName == "Name")
        {
            if (this.Name == "")
                result = "Name can not be empty";
        }
        return result;
    }
} 

Define / assign your message which you want to display when data goes wrong. Here, I used result variable to store the error message.

Finally our Customer class looks like:

C#
public class Customer : IDataErrorInfo
{
    public string Name
    {
        get;
        set;
    }       

    public string Error
    {
        get { return null; }
    }

    public string this[string columnName]
    {
        get
        {
            string result = string.Empty;
            if (columnName == "Name")
            {
                if (this.Name == "")
                    result = "Name can not be empty";
            }
            return result;
        }
    }
}

That’s all in the code behind. Now we can move into the XAML part.

Now open “MainWindow.xaml”. Just create two textboxes with the necessary settings.

  1. I created two text boxes inside the grid like below:
    C#
    <TextBox HorizontalAlignment="Left" x:Name="SampleTextBox" Height="35" Width="150" />
    <TextBox HorizontalAlignment="Right" x:Name="eTextBox" Height="35" Width="150" Text="Super" />
  2. Create style in Resources section for easy readability. Else, you can have the style property definition inside <Textbox.Style></Textbox.Style>. I always prefer the first way, i.e., inside resources section to reuse the style wherever we want.
    XML
    <Style x:Key="TextErrorStyle" TargetType="{x:Type TextBox}"> </Style>
    Explanation
    1. Suppose we do have an error in text box, then what are all the things we want to notify to the user that something has gone wrong. (Basically tooltip, and changing background color of textbox).

      This style will apply only if “Validation.HasError” returns true. So we should specify it in Trigger property.

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

      Here, we should understand about relative source which will get the values from TextBox control (here SampleTextBox) by specifying RelativeSource.Self (which control uses this style, i.e., TextErrorStyle, we will get all values of that control then which property we’re specifying in Path property that will be assigned to ToolTip.

    2. If suppose I want to draw a red color over the text box rather than changing background color. For that, we should define the “Validation.ErrorTemplate” property as below:
      XML
      <Setter Property="Validation.ErrorTemplate">
          <Setter.Value>
              <ControlTemplate x:Name="TextErrorTemplate">
                  <DockPanel>
                      <Border BorderBrush="Red" BorderThickness="1">
                          <AdornedElementPlaceholder/>
                      </Border>
                      <TextBlock FontSize="20" Foreground="Red">*?*</TextBlock>
                 </DockPanel>
              </ControlTemplate>
          </Setter.Value>
      </Setter>
      Tip

      <AdornedElementPlaceholder/> - It is our control here “SampleTextBox”, based upon this we should place our exclamation or question mark. Basically, we cannot hold two more controls without container (Here DockPanel) in <ControlTemplate />, but if our requirement is showing only one control then we can neglect container.

      That’s all about style. Now we can move to attaching defined properties to the “SampleTextBox” control.

  3. I bound all the properties to the text box control as below. We need to create an instance for Customer class. We can follow either in code behind or XAML itself. I used to create in XAML like below.

    Import the solution along with project namespace in XAML.

    XML
    xmlns:local="clr-namespace:WpfValidation"
    
    <Window.Resources>
        <local:Customer x:Key="CustomerInstance" Name="Srini"/>
    </Window.Resources>

    Here, we can pass the default value for our created Name property.

    XML
    <TextBox HorizontalAlignment="Left" 
    x:Name="SampleTextBox" Height="35" Width="150" 
        Style="{StaticResource TextErrorStyle}">
        <TextBox.Text>
            <Binding Path="Name" Source="{StaticResource CustomerInstance}" 
            UpdateSourceTrigger="PropertyChanged" />
        </TextBox.Text>
    </TextBox>

    Here I used “UpdateSourceTrigger = PropertyChanged” since I want to get notification whenever any keys are entered/deleted. Still it is not over. Two more things are remaining to achieve our target.

  4. Then now we have used IDataErrorInfo in this project, so we have to use "ValidatesOnDataErrors =”True”".
  5. Finally, ValidationRules needs to be set. DataErrorValidationRule, ExceptionValidationRule, NotifyDataErrorValidationRule are there. I need to throw an exception if my source property gets updated.
    C#
    <TextBox HorizontalAlignment="Left" 
    x:Name="SampleTextBox" Height="35" Width="150">
        <TextBox.Text>
            <Binding Path="Name" Source="{StaticResource CustomerInstance}" 
            ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <ExceptionValidationRule></ExceptionValidationRule>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

Hope it helps you. Thanks a lot for spending your valuable time to read my article. I welcome your comments and suggestions. If you have any feedback, it will be more helpful to improve myself.

Please find the attached sample project for the reference.

History

Updated this post with Part II as well. You can find the link for the Part II article at the top of this post.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
Simple Concept for achieving anything "Practice... Practice... Practice..." will make you stronger irrespective of the background of person!!!".

Comments and Discussions

 
QuestionNo error message displayed...only *?* Pin
Paul Reed30-May-19 7:48
Paul Reed30-May-19 7:48 
GeneralMy vote of 4 Pin
Moumit Mondal28-Sep-15 3:51
Moumit Mondal28-Sep-15 3:51 
GeneralMy vote of 4 Pin
MahBulgariaReborn5-Jan-15 9:31
MahBulgariaReborn5-Jan-15 9:31 
GeneralMy vote of 5 Pin
tal_segal5-Jan-15 5:17
tal_segal5-Jan-15 5:17 
Very good, clear, simple, Thank you!
QuestionWPF Validation Pin
Member 113474881-Jan-15 22:21
Member 113474881-Jan-15 22:21 
GeneralNice Article. Pin
Nomesh G1-Jan-15 21:08
Nomesh G1-Jan-15 21:08 
QuestionIs this a conventional way? Pin
csakii1-Jan-15 3:37
csakii1-Jan-15 3:37 
AnswerRe: Is this a conventional way? Pin
K K Srinivasan1-Jan-15 8:01
K K Srinivasan1-Jan-15 8:01 
AnswerRe: Is this a conventional way? Pin
Nomesh G1-Jan-15 20:09
Nomesh G1-Jan-15 20:09 
GeneralRe: Is this a conventional way? Pin
K K Srinivasan1-Jan-15 20:33
K K Srinivasan1-Jan-15 20:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.