Extend the Textbox Control to Validate Against Regular Expressions

Introduction

This article describes an approach to validating text box entries against a regular expression. The approach described relies on a custom control built to extend the regular text box control. The custom text box control contains a property used to hold a regular expression as well as a function used to validate the contents of the text box against the regular expression. In the example provided, the validation function is used in conjunction with an error provider control. Whenever a custom control fails the validation test, the error provider is used to display an error indication adjacent to the control containing the error.

Image1.jpg

Figure 1.  Custom Textbox Control used with an Error Provider

Getting Started.

The solution provided with this download contains two projects. The first project is a class library called "RegExControls" which contains a class called "RegExTextBox"; this class is an extended text box control that provides the means to store a regular expression and to test the text box text against the regular expression. The second project is a test windows form application called "TestRegExControls"; this project contains a single windows form that shows five examples of the extended text box control in use in conjunction with an error control. The windows form application contains example code showing ways in which the error provided control can be used to mark the extended text box control if that control fails validation.

Image2.jpg

Figure 2.  Solution Explorer

All examples were written using Visual Studio 2005 and are in C#; open the solution into the IDE and examine the code. 

Project 1 - RegExControls

The Code for RegExTextBox:

The class extends the standard text box control. The class adds a property used to contain a regular expression and it contains a validation function that may be evoked to validate the contents of the text box control against a regular expression.

The class begins with the following code:

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace RegExControls
{
    public partial class RegExTextBox : TextBox
    {

Note that in addition to the default class imports, that the regular expression library is also included. The class declaration shows that it inherits from TextBox.

Following the class declaration, there is a region set up to contain member variable declarations, in this case the region only contains a single declaration:

#region "Declarations"
        private string mRegularExpression;
#endregion

The variable declared is used to contain the regular expression that will service is the basis for validating the text box content.  Public access to this member variable is provided through a property. This property is defined in the "Properties" region which contains the following code:

#region "Properties"
    public string Regular_Expression
    {
        get
        {
            return mRegularExpression;
        }
        set
        {
            mRegularExpression = value;
        }
    }
#endregion

After the property region, the next section of code contains the constructor which is in its default condition:

#region "Constructor"
    public RegExTextBox()
    {
        InitializeComponent();
    }
#endregion

The next region contains the class methods; this region contains an OnPaint event handler which is in its default condition and it contains a validation method which is used to validate the content of the text box against the user supplied regular expression:

#region "Methods"
    protected override void OnPaint(PaintEventArgs pe)
    {
        // TODO: Add custom paint code here
        // Calling the base class OnPaint
        base.OnPaint(pe);
    }
    public bool ValidateControl()
    {
        string TextToValidate;
        Regex expression;
        try
        {
            TextToValidate = this.Text;
            expression = new Regex(Regular_Expression);
        }
        catch
        {
            return false;
        }
        // test text with expression
        if (expression.IsMatch(TextToValidate))
        {
            return true;
        }
        else
        {
            // no match
            return false;
        }
    }
#endregion

The validation function works by first validating that the custom control contains both text and a user supplied regular expression. If both are present, the validation function sets to variables to contain the text as a string and the regular expression as a regex variable. After these values are set, the regular expression's is match method is evoked and used to compare the text against the regular expression. If the patterns match, the function returns true, if they do not match, the function returns false.

This concluded the discussion of the custom text box control. The next section of this document will provide an example of a win forms application using several of the controls to validate user input against regular expressions.

Project 2 - TestRegExControls

The Code for Form1:

The project contains only a single form. The form contains a group box which contains five labels and five of the custom regular expression text box controls. 

Each of the labels describes the input required for the text box and each of the regular expression text box controls contains a regular expression used to test the control's text property. 

Below the group box are two button controls, one is used to validate the form's input and the other is used to validate and then exit the form (by closing the application). The validate button calls a validate function which will test each regular expression text box and fail on any detected invalid entries. The submit button does the same thing but allows the application to close only if none of the regular expression tests fails.

In addition to the visible content, the form also has an associate error provider. The error provider is used to mark any controls that fail validation.

Image3.jpg

Figure 3.  Form1 in the IDE Designer

The control's regular expression may be set at either run or design time; the expression must not contain the '^' at the start or the '$' at end of the string.

Image4.jpg

Figure 4.  Regular Expression Set at Design Time

The Form1 class is initialized with the defaults:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestRegExControls
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

After the class is initiated, a region called "Handle Validations" is defined and for each of the regular expression text boxes, the validating event is handled; the first one looks like this:

#region "Handle Validations"
    private void regExTextBox1_Validating(object sender, CancelEventArgs e)
    {
        // test the control for invalid input
        if (regExTextBox1.ValidateControl() == false)
        {
            // display error if user input is invalid
            errorProvider1.SetError(regExTextBox1, "Invalid SSN (e.g., 123-22-3344)");
        }
        else
        {
            // set error message to nothing if control
            // passes validation
            errorProvider1.SetError(regExTextBox1, "");
        }
    }

All five of the validating event handlers work essentially the same but show different text when the user hovers over the error indication. The validating event handler calls the control's ValidateControl method which validates the control's text property against its regular expression. If the validate control method returns a false, the error provider is used to set the control's error and the text for the error provider is set. In the example provided above, the control is validating the text against a regular expression used to validate a social security number; if the validate control function returns a false, the user is shown the correct format for a valid entry. 

If the control passes validations, the error provider's text is set to an empty string and as such the error provider's error indication will not be shown to the user.

The next method provided in this region is used to validate all of the controls; this method is called by the validate button and the submit button to check the form for invalid entries:

private bool PerformFormValidation()
{
    // check for errors to set return value
    if (regExTextBox1.ValidateControl() == false)
    {
        return false;
    }
    if (regExTextBox2.ValidateControl() == false)
    {
        return false;
    }
    if (regExTextBox3.ValidateControl() == false)
    {
        return false;
    }
    if (regExTextBox4.ValidateControl() == false)
    {
        return false;
    }
    if (regExTextBox5.ValidateControl() == false)
    {
        return false;
    }
    // if it has not found an invalid control, return with true
    return true;
}

The last code in the application is used to handle the button event clicks for the validate and submit buttons. The submit (btnExit) button's click event handler is as follows:

private void btnExit_Click(object sender, EventArgs e)
{
    // test the form before allowing the user to close it
    bool valResult = PerformFormValidation();
    if (valResult == true)
        Application.Exit();
    else
        MessageBox.Show("Fix errors on this page prior to closing form");
}

This click event handler calls the PerformFormValidation method; the returned value is used to set a boolean and the boolean is then evaluated and if true, the application exists, if not the user is shown a message instructing them to fix the errors before closing the form.

The validate button's click event handler works essentially the same way but it only used to tell the user whether or not the form contains invalid entries: 

private void btnValidate_Click(object sender, EventArgs e)
{
    // test the form
    bool valResult = PerformFormValidation();
    if (valResult == true)
        MessageBox.Show("All form fields are valid");
    else
        MessageBox.Show("This form contains errors");
}

That is all there is to the test application's Form1 class code.

Summary.

This article demonstrates an approach to validating user input against a regular expression in a win forms application. The approach is based upon extending the standard win forms text box control to allow storage of a regular expression and to provide the means to validate the text contained in the control against the pattern defined in the regular expression. The article further described how the extended text box control could be used in conjunction with an error provider to display meaningful information to the user if the control's validation function indicates a mismatch between the control's text and the regular expression provided with the control.