Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Self-validating Textbox

0.00/5 (No votes)
7 Aug 2007 1  
An article on a textbox that validates input on keypress

Screenshot - Validating1.jpg

Introduction

Often, it is necessary to control the input of a textbox to maintain the successful functioning of an application, particularly those involving accounting and databases. This textbox controls what the user can type into it. It does this by validating the input character on KeyPress. It has nine modes that are all useful in different situations and can be changed via the ValidationFormat property in design or runtime.

As opposed to other validating textboxes, this is all done on KeyPress. So, there is no possible way that the user can input the wrong data. Although it has elements similar to the masked textbox, it provides functionality for alphanumeric, decimal, currency and, uniquely, capitalisation. Capitalisation is useful for when the user inputs their name into your fields. This way, when this information is stored, it is in the correct format in case the use has been forgotten.

Note: This was made in Visual Studio 2005 on Windows XP using .NET Framework 2.0.

Features

9 ValidationFormat Modes

  • None: Allows any characters.
  • Alphabetical: Allows only letters.
  • Numeric: Allows only numbers.
  • Alphanumeric: Allows only letters and numbers.
  • Decimal: Allows numbers and one decimal point. Accommodates for locality and difference in currency symbols and separator characters.
  • CapitaliseEachWordAlphabetical: Allows only letters and capitalises the first letter of each word.
  • CapitaliseEachWordAlphanumeric: Allows only letters and numbers and capitalises the first letter of each word.
  • CapitaliseEachWordAll: Allows any characters and capitalises the first letter of each word.
  • Currency: Allows only numbers, one currency symbol, one decimal separator and unlimited group separators. Accommodates for locality and difference in currency symbols and separator characters.
  • UpperCaseAlphabetical: Allows only upper case letters; letters typed in lower case will be converted to upper case.
  • UpperCaseAlphabetical: Allows only upper case letters and numbers; letters typed in lower case will be converted to upper case.
  • LowerCaseAlphabetical: Allows only lower case letters; letters typed in upper case will be converted to lower case.
  • LowerCaseAlphabetical: Allows only lower case letters and numbers; letters typed in upper case will be converted to lower case.

Validation on KeyPress, Leave and TextChanged

The validation of this control is done in 3 phases. The first is on the KeyPress event. If the user types a key that is not allowed by ValidationFormat, the key is simply rejected. The second phase of validation occurs on the Leave event. When the textbox loses focus, it checks that the contents of the textbox are correct in the unlikely event of the introduction of unwanted characters. In the third phase, the control validates on the TextChanged event. This final phase is enacted in the event that the user performs a paste in the textbox.

New Properties

This text box has five new properties compared to the standard textbox and all have a separate role in the validation. The first new property is, of course, the ValidationFormat property. This allows the designer to select what format they want their textbox in, whether it be Numeric, Alphabetical or any of the other modes.

The second new property is the ValidInput property. At OnLeave or TextChanged validation, if some form of invalid data is entered into the textbox, the InvalidInput property is set to false. This lets the designer know when there is invalid data.

The third new property is the AllowNull property. If this is set to false, then if the textbox is empty or becomes empty, the ValidInput property is set to false. This lets the designer know when there is a problem with the data.

The fourth new property is the DisplayTickOnValid property. As opposed to the normal error displaying an icon only when the user gets it wrong, this textbox displays an icon when the user gets it right as well, but only if you want it to.

The fifth new property is the ErrorMessage property, which will be discussed in the next section.

Everyone Knows When There's a Problem

I felt that one important thing when designing this was having not only the designer know when the textbox throws an error, but also letting the user know. To allow this, I added ErrorProvider to the textbox. When there is a problem with validation, ErrorProvider is set to display with an attached error, i.e. the tooltip that shows up over the error icon. The textbox then sets its ValidInput property to false, letting the designer know that there is a problem. It also sets its ErrorMessage property to match the error associated with ErrorProvider. There are 3 benefits to doing all of this:

  1. The user knows when there is a problem, allowing the user to correct it.
  2. The textbox indicates when there is a problem, allowing features in the program to take the correct action such as disabling a save button, etc.
  3. The program can access the associated error and display it to the user, letting the user know what is wrong.

Events

Associated with each of the new properties is a new event. Each new property has an associated PropertyChanged event. This is useful because designers can incorporate code that can:

  1. Allow them to take action when there is an error.
  2. Allow properties to be changed at runtime and have available reactions to those changes.
  3. Display, to the user, an error message when ErrorMessage is changed.

Using the Code

The code is simple, mostly. It is just a matter of compiling the control into a DLL and adding that to your toolbox. Then you can use it in any application you want. Here's how to add it to your toolbox:

  1. Compile the control.
  2. Right click the Toolbox -> Choose Items -> Browse for the DLL -> Add it and Apply -> Use the control.

The most useful part about this control, however, is the new ValidInput property I have added. When the textbox loses focus, it verifies that its content is valid by running a check against its current ValidationFormat. If the check returns a value specifying that the input is not valid, the ValidInput property is set to False. When the user goes to continue or commit the data, your program can check the textboxes. It sees if they are all valid and allows or disallows continuation. In addition to this, the control includes an in-built ErrorProvider that will show the user that their input is invalid, giving them a chance to change it.

The Code (or Parts of It)

Declarations Regarding Globalization

Imports System.Globalization.NumberFormatInfo
Dim DSep As String = 
    CurrentInfo.NumberDecimalSeparator 
    ' finds decimal separator for local region
Dim GSep As String = 
    CurrentInfo.NumberGroupSeparator 
    ' finds group separator for local region
Dim CSym As String = 
    CurrentInfo.CurrencySymbol 
    ' finds currency symbol for local region

Alphabetical

If Char.IsLetter(e.Keychar) = False Then
    e.Handled = True
End If

Numeric

If Char.IsNumber(e.Keychar) = False Then
    e.Handled = True
End If

Alphanumeric

If Char.IsLetterorDigit(e.Keychar) = False Then
    e.Handled = True
End If

Decimal

If Char.IsNumber(e.KeyChar) = False Then
    If e.KeyChar = CChar(DSep) Then
        If Me.Text.Contains(DSep) Then '
            e.Handled = True           ' Allows only one decimal separator
        End If                         '
    Else
        e.Handled = True
    End If
End If

Checking Allow Null and Acting Appropriately

This is if the text property of the textbox is null.

If Me.AllowNull = True Then
    Valid()
Else
    Me.InvalidErrorProvider.SetError(Me, 
        "Invalid Input: This textbox must not be empty.")
    Invalid()
End If 

Private Sub Valid()
    Me.InvalidErrorProvider.Clear()
    Me.ErrorMessage = Nothing
    Me.ValidInput = True
End Sub

Private Sub Invalid()
    Me.ErrorMessage = Me.InvalidErrorProvider.GetError(Me)
    Me.ValidInput = False
End Sub

The rest of the code is far too long to post in one large block.

Points of Interest

Capitalising was the most difficult part to get right, as there are so many variables. If the user decides to backspace, it has to check if it needs to capitalise. Then it has to capitalise the first letter and check -- in some instances -- if it is even a letter. Co-ordinating all these was a bit tricky and is probably a bit messy, so feel free to tidy up the code. An interesting thing I found was that with backspace and space, there has to be an exception for the backspace and space characters because they are blocked along with special characters.

One important thing that I had to focus on, which I hadn't originally considered, was managing the currency field. In particular, I needed to consider what and how money values were entered. Because different countries use different formats for their currency, it was necessary to tap into the System.Globalization namespace and work with the different elements it provided for allowing international compatibility. These included CurrentInfo.NumberDecimalSeparator, CurrentInfo.NumberGroupSeparator and CurrentInfo.CurrencySymbol.

History

  • July 3, 2007 -- Original version posted
  • July 6, 2007 -- Article updated
  • July 9, 2007 -- Article updated
  • August 7, 2007 -- Article and download updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here