Click here to Skip to main content
15,881,173 members
Articles / Desktop Programming / WPF

WPF Validation

Rate me:
Please Sign up or sign in to vote.
3.26/5 (9 votes)
30 Jan 2012CPOL3 min read 79.8K   2.8K   13   21
This article describes the Validation process in WPF

Validation2.jpg

Validation3.jpg

Introduction

In this article, I have discussed the validation process in WPF. For understanding the validation process, I have created a simple application which divides numbers entered in text boxes and displays the result in a label. If the user enters invalid data, it displays the appropriate error messages.

Background

While dividing two numbers, the most likely issues can be related to handling of non-numeric data and dividing by zero. In this article, I have described how to do data validation for such errors. In this application, I have validated that the user does not enter non-numeric data and zero in the textboxes. I have developed the application using Microsoft Visual C# 2010 Express Edition (Microsoft .NET Framework Version 4.0.21006).

Using the Code

To use the validator function, we must first declare the namespace where it will be found. This is done by adding an attribute for the root Window element as follows:

XML
xmlns:local="clr-namespace:ValidationExample"

The complete XAML code for the window element is as follows:

XML
<Window x:Class="ValidationExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ValidationExample"
    Title="Number Division" Height="300" Width="300"
    Loaded="Window_Loaded">

In the above code, the Window Loaded event called Window_Loaded is added to initialize our data object with initial values. The code-behind code for the Window_Loaded event is as follows:

C#
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    MyData data = new MyData("", "");
    t1.DataContext = data;
    t2.DataContext = data;
}

The MyData class represents our data. It consists of three properties FirstNumber, SecondNumber and Division. Its code is as follows:

C#
public class MyData
{
    public object FirstNumber    // FirstNumber Property
    {
        get;
        set;
    }
    public object SecondNumber    // SecondNumber Property
    {
        get;
        set;
    }
    public object Division        // Division Property
    {
        get
        {
            try
            {
                double n1 = Convert.ToDouble(FirstNumber.ToString());
                double n2 = Convert.ToDouble(SecondNumber.ToString());
                double n3 = n1 / n2;
                return n3;
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
    public MyData(object FirstNumber, object SecondNumber)    // Constructor
    {
        this.FirstNumber = FirstNumber;
        this.SecondNumber = SecondNumber;
    }
}

To display the result of division, I have created a template with a key called myTemplate as follows:

XML
<Window.Resources>
    <DataTemplate x:Key="myTemplate" DataType="ValidationExample.MyData">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Division: "/>
            <TextBlock Text="{Binding Path=Division}"/>
        </StackPanel>
    </DataTemplate>

The above code displays the result of division by binding the Division property to a TextBlock. To display error if any validation error occurs, I have created a control template with a key called errorTemplate as follows:

XML
<ControlTemplate x:Key="errorTemplate">
        <StackPanel>
            <TextBlock Foreground="Red">Invalid Value!!!</TextBlock>
            <AdornedElementPlaceholder/>
        </StackPanel>
    </ControlTemplate>
</Window.Resources>

In the above code, the AdornedElementPlaceholder element is used to display the error message. The user interface to accept two numbers from the user and display the result of division is created as follows:

XML
    <Canvas>
        <Label Canvas.Left="10" Canvas.Top="40" Content="Enter First Number: "/>
        <TextBox x:Name="t1" Canvas.Left="135" Canvas.Top="40" Width="100" 
        Height="30" Validation.ErrorTemplate="{StaticResource errorTemplate}" 
        Validation.Error="NumberError">
            <Binding Path="FirstNumber" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:NumberValidator/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox>
        <Label Canvas.Left="10" Canvas.Top="80" Content="Enter Second Number: "/>
        <TextBox x:Name="t2" Canvas.Left="135" Canvas.Top="80" Width="100" 
        Height="30" Validation.ErrorTemplate="{StaticResource errorTemplate}" 
        Validation.Error="NumberError">
            <Binding Path="SecondNumber" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:NumberValidator/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox>
        <Button Name="b1" Canvas.Left="10" Canvas.Top="120" Width="225" 
        Content="Divide" Click="b1_Click"/>
        <Label x:Name="lblResult" Canvas.Left="10" 
        Canvas.Top="160" ContentTemplate="{StaticResource myTemplate}"/>
    </Canvas>
</Window>

In the above code, the Canvas element is used as a container. Two TextBoxes t1 and t2 are bound to the properties FirstNumber and SecondNumber respectively. The error templates for the two textboxes are specified using the Validation.ErrorTemplate attribute.

The <Binding> child element of the textbox is used to bind the textbox to its corresponding data property (FirstNumber and SecondNumber). The custom validation class is specified by the <local:NumberValidator/> element. The Button b1 is used to divide the numbers and the result is displayed in a label called lblResult. The template for the label is specified using the ContentTemplate attribute.

The problem with error template is that it always displays a generic error message. To display specific error as a tooltip, the Validation.Error attribute is used. The Validation.Error attribute is used to link the textboxes to the error function called NumberError. The code-behind code for the NumberError function is as follows:

C#
private void NumberError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)    // Validation Error Occurred
    {
        ((Control)sender).ToolTip = e.Error.ErrorContent.ToString();
    }
    else                        // No Error
    {
        ((Control)sender).ToolTip = "";
    }
}

The above code checks if invalid data is entered in the textboxes and displays the error message in the form of a tooltip and resets the tooltip if the error is removed.

The code for the Validation function is as follows:

C#
    public class NumberValidator : ValidationRule
    {
        public override ValidationResult Validate
        (object value, System.Globalization.CultureInfo cultureInfo)
        {
            double number = 0;
            try
            {
                number = Convert.ToDouble(value.ToString());  // Check for numeric value
            }
            catch (Exception)
            {
                return new ValidationResult(false, "Value must be numeric");
            }
            if (number == 0)                    // Check for non-zero value
            {
                return new ValidationResult(false, "Value must be non-zero");
            }
            return new ValidationResult(true, null);
        }
    }
}

The custom validation class must inherit from the ValidationRule class and it must override the Validate method. The Validate method takes two parameters. The first parameter is the object to be validated. The second parameter is of the type System.Globalization.CultureInfo. In this case, the Validate function checks whether the value is numeric and non-zero and returns a ValidationResult object. The first parameter of the ValidationResult constructor is boolean and indicates that the data is valid if it is true and invalid otherwise. The second parameter is the error message string in case of invalid data and null otherwise.

Points of Interest

I hope that this article will help in understanding the basics of WPF validation in a simple way.

History

  • 30th January, 2012: Initial version

License

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


Written By
Instructor / Trainer NIIT, India
India India
I am a trainer by profession. Currently I am working with iFuture Technologies(India) as a Senior Faculty. I enjoy programming as a hobby. During my career I have seen the growth and decline of many technologies, many of them being my favorites like Flash, WPF, Windows Mobile Development. Few of my current favorites are Android, Xamarin and Python, though I also like traditional and evergreen languages like PHP, C#, Visual Basic and Java.

Apart from computers, my favorite pastime is bicycling.

Comments and Discussions

 
SuggestionDesign Reconsideration: Basics but important things Pin
Bhanu Chhabra27-Oct-16 20:32
Bhanu Chhabra27-Oct-16 20:32 
GeneralMy vote of 4 Pin
HOSSEIN.AB24-Oct-12 1:15
HOSSEIN.AB24-Oct-12 1:15 
GeneralRe: My vote of 4 Pin
Azim Zahir24-Oct-12 18:10
Azim Zahir24-Oct-12 18:10 
GeneralMy vote of 3 Pin
net_201021-Oct-12 20:36
net_201021-Oct-12 20:36 
GeneralRe: My vote of 3 Pin
Azim Zahir22-Oct-12 18:11
Azim Zahir22-Oct-12 18:11 
GeneralMy Vote of 3 Pin
net_201021-Oct-12 20:34
net_201021-Oct-12 20:34 
GeneralMy vote of 3 Pin
George V. Lache13-Feb-12 15:37
George V. Lache13-Feb-12 15:37 
GeneralMy vote of 3 Pin
Paul Conrad30-Jan-12 8:59
professionalPaul Conrad30-Jan-12 8:59 
I have to agree with the other commenters.
GeneralMy vote of 3 Pin
Shahin Khorshidnia30-Jan-12 5:21
professionalShahin Khorshidnia30-Jan-12 5:21 
GeneralMy vote of 3 Pin
Sacha Barber30-Jan-12 4:28
Sacha Barber30-Jan-12 4:28 
QuestionMmmm not great Pin
Sacha Barber30-Jan-12 4:27
Sacha Barber30-Jan-12 4:27 
AnswerRe: Mmmm not great Pin
Dave Kerr30-Jan-12 4:48
mentorDave Kerr30-Jan-12 4:48 
GeneralRe: Mmmm not great Pin
Sacha Barber30-Jan-12 4:58
Sacha Barber30-Jan-12 4:58 
GeneralRe: Mmmm not great Pin
Dave Kerr30-Jan-12 5:08
mentorDave Kerr30-Jan-12 5:08 
GeneralRe: Mmmm not great Pin
Sacha Barber30-Jan-12 6:10
Sacha Barber30-Jan-12 6:10 
GeneralRe: Mmmm not great Pin
Member 882051412-Jul-12 13:42
Member 882051412-Jul-12 13:42 
GeneralRe: Mmmm not great Pin
Sacha Barber12-Jul-12 19:38
Sacha Barber12-Jul-12 19:38 
GeneralRe: Mmmm not great Pin
Sacha Barber13-Jul-12 3:00
Sacha Barber13-Jul-12 3:00 
GeneralRe: Mmmm not great Pin
Member 882051413-Jul-12 15:23
Member 882051413-Jul-12 15:23 
GeneralRe: Mmmm not great Pin
Member 882051415-Jul-12 13:39
Member 882051415-Jul-12 13:39 
AnswerRe: Mmmm not great Pin
Azim Zahir30-Jan-12 18:37
Azim Zahir30-Jan-12 18:37 

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.