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

WPF Validation - using INotifyDataErrorInfo

Rate me:
Please Sign up or sign in to vote.
4.71/5 (17 votes)
15 Feb 2015CPOL2 min read 76.1K   3.3K   22   7
Focus on WPF Novice, to do Data Validation using INotifyDataErrorInfo interface easily

Introduction

Part I: implements IDataErrorInfo interface

I really want to say thanks to readers who read my previous post “WPF Validation – using DataErrorInfo” for their comments and wishes.

Now I got time to write another post in Part - II “WPF Validation – using INotifyDataErrorInfo”.

Using the Code

It is always better to have some theoretical knowledge before implementing the same.

Let’s dive into that.

Implementation of INotifyDataErrorInfo interface returns 3 things:

  • HasErrors bool property
  • GetErrors IEnumerable type
  • ErrorsChanged – Event

Two things are the main difference compared to IDataErrorInfo interface implementation.

  • Checks the validation asynchronously
  • The ability to store and retrieve multiple errors for single property

We will see this in a very detailed way in the below part of this post.

First, we can see the coding side, then go for XAML styling later.

Step 1

Implement INotifyDataErrorInfo interface in Customer class.

C#
public class Customer : INotifyDataErrorInfo
{
       public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;     

       public System.Collections.IEnumerable GetErrors(string propertyName)
       { }
       public bool HasErrors
       {
          get
          {              
            return true;
           }
       }
}

Step 2

Define Dictionary<string, List<string>> locally.

C#
Dictionary<string, List<string>> propErrors = new Dictionary<string, List<string>>();

Here is one for property name, another one for list of errors for the given property.

Step 3

We should check the HasErrors property, whether it returns true or not. If it returns true, then only data validation will be highlighted. Data validation will not be notified to the user when errors content is there but this property returns false. So make sure that this property returns true based on error values count from propErrors.

C#
public bool HasErrors
{
   get
   {
      try
      {
         var propErrorsCount = propErrors.Values.FirstOrDefault(r =>r.Count>0);
         if (propErrorsCount != null)
              return true;
          else
              return false;
       }
       catch { }
       return true;
    }
 }

Step 4

We should get the list of defined errors from the Dictionary.

C#
public System.Collections.IEnumerable GetErrors(string propertyName)
{
     List<string> errors = new List<string>();
     if (propertyName != null)
     {
         propErrors.TryGetValue (propertyName, out errors);
         return errors;
     }
     else
         return null;
}

Step 5

In the OnPropertyChanged() method, we call Validate() to get the errors for each property we have in the Customer class.

Some cases, we will have more validation strings for one property. Those defined validation strings will be added into List<string> listErrors; this list is assigned to dictionary.

C#
propErrors ["Name"] = listErrors;

If listErrors. Count > 0, then raise the ErrorsChanged Event.

That's all coding. Now we can go for styling in XAML.

XAML part - Styling part remains the same as what we have done for IDataErrorInfo implementation. Only one thing is replace ValidatesOnDataErrors with ValidatesOnNotifyDataErrors property to true.

XML
<Style x:Key="TextErrorStyle" TargetType="{x:Type TextBox}">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate x:Name="TextErrorTemplate">
                        <DockPanel LastChildFill="True">
                            <AdornedElementPlaceholder>
                                <Border BorderBrush="Red" 
                                BorderThickness="2"/>                       
                            </AdornedElementPlaceholder>
                            <TextBlock FontSize="20" 
                            Foreground="Red">*?*</TextBlock>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError" 
                Value="True">                    
                    <Setter Property="ToolTip" 
                    Value="{Binding RelativeSource=
            {x:Static RelativeSource.Self},
            Path=(Validation.Errors)[0].ErrorContent}"></Setter>
                </Trigger>
            </Style.Triggers>
</Style> 

Then bind this style to the text box control which we want to validate.

XML
<TextBox HorizontalAlignment="Left" Margin="10" 
x:Name="SampleTextBox" Height="35" Width="150" 
Style="{StaticResource TextErrorStyle}"                 
   Text="{Binding Source={StaticResource CustomerInstance},Path=Name,Mode=TwoWay,
   ValidatesOnNotifyDataErrors=True,UpdateSourceTrigger=PropertyChanged}">            
</TextBox> 

Here Source is nothing but the Customer class instance:

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

That’s all guys. :)

I've attached the code sample for your easy reference. Anyway, if you want to give it a try, then just get my previous post code sample, from there you can just try to implement this concept.

Hope you all got this concept well. I welcome your comments, questions and suggestions if any.

Points of Interest

I learnt how to use and when to use TPL while implementing this concept for sample application since INotifyDataErrorInfo can be done asynchronously.

History

XAML part styling has been added.

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

 
QuestionException Handling Pin
Member 1113244918-Aug-15 5:09
Member 1113244918-Aug-15 5:09 
QuestionValidation as Event? Pin
Member 1113244918-Aug-15 5:04
Member 1113244918-Aug-15 5:04 
QuestionWho calls GetErrors? Pin
Member 1113244918-Aug-15 5:02
Member 1113244918-Aug-15 5:02 
QuestionINotifyPropertyChanged Pin
Member 1113244918-Aug-15 4:21
Member 1113244918-Aug-15 4:21 
AnswerRe: INotifyPropertyChanged Pin
Member 1113244918-Aug-15 4:28
Member 1113244918-Aug-15 4:28 
Questionxaml Pin
Sacha Barber15-Feb-15 12:36
Sacha Barber15-Feb-15 12:36 
Please site the binding arrangement on xaml part otherwise the article is not complete
AnswerRe: xaml Pin
K K Srinivasan15-Feb-15 15:20
K K Srinivasan15-Feb-15 15:20 

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.