Click here to Skip to main content
Click here to Skip to main content

WPF Validation

, 30 Jan 2012
Rate this:
Please Sign up or sign in to vote.
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:

xmlns:local="clr-namespace:ValidationExample"

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

<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:

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:

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:

<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:

<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:

    <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:

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:

    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)

About the Author

Azim Zahir
Instructor / Trainer NIIT, India
India India
I am a trainer by profession. Currently I am working with NIIT (Mumbai, India) as a Senior Faculty. I enjoy programming as a hobby. My favorite technologies are Flash, Flex and Silverlight.
 
Of late I have developed keen interest in WPF and Windows Mobile programming.
 
Apart from computers, my favorite pastime is bicycling.

Comments and Discussions

 
GeneralMy Vote of 3 Pinmembernet_201021-Oct-12 20:34 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 30 Jan 2012
Article Copyright 2012 by Azim Zahir
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid