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

A general purpose base class for TextBox filtering

, 20 Mar 2007
Rate this:
Please Sign up or sign in to vote.
This article describes a base class, FilterTextBox, that can be used to implement flexible filtering for a TextBox control.

Screenshot - FilterTextBox.png

Introduction

Have you ever wanted to filter user input for a TextBox control? Are the other solutions on Code Project too narrowly focused for your requirements? Do you just want to better understand filtering in general? If so, this article is for you.

The article describes a base class, FilterTextBox, that can be used to implement flexible filtering for a TextBox control.

The class exposes a new event TextChanging that fires when the Text property is about to change, but before it has actually changed. The event arguments include an AfterText property to preview the proposed changes. They also include a Cancel property that can be modified to cancel the changes.

Background

What do I mean by "filtering"? What if you wanted a TextBox control that restricted user input to only numbers? How would you go about implementing this? One solution would be to use the Validating event. Unfortunately, this event does not fire until after focus leaves the control. So the user will, at least temporarily, see the invalid input.

Wouldn't it be nice to prevent these characters from being seen in the first place? This is the problem solved by filtering.

The truth is, if your filtering needs are as simple as those just described, you should probably use the MaskedTextBox control introduced in .NET 2.0.

Why provide another solution here? This is a fair question. In my case, I don't have .NET 2.0 yet, my filtering needs are more complex, and I just like to understand how things work.

I provide this class in case others have similar needs. Also, I think a TextChanging event might be useful for other purposes.

Using the code

The FilterTextBox control inherits from the standard .NET TextBox control. It extends the capabilities of this control by adding the following members...

Name Type Description
TextChanging event Event first when Text property is changing, but before it is changed.
OnTextChanging() void Invoked when Text property is changing, but before it is changed.
TextChangingWarn() void Invoked when event is canceled. If not overridden, it sounds an audible beep.
CaretPosition int Index of caret position within text.

The most common use of the FilterTextBox control is likely to be as a base class for other controls. In this case, the simplest way to use it is by overriding the OnTextChanging method. The following example, from the included NumericTextBox control, demonstrates this usage. In this example, newly inserted text is scanned for non-numeric characters. If any are found, the Cancel property of the event arguments is set to true. Setting Cancel to this value, prevents the Text from being inserted.

protected override void OnTextChanging (
    TextChangingEventArgs e )
{
    // If not cancelling and not deleting...
    if (!e.Cancel && !e.IsDelete)
    {
        // Get text we need to validate
        string text;
        if (e.IsAssign)
            text = e.AfterText;
        else
            text = e.InsertedText;

        // Loop to validate text...
        foreach(char charValue in text)
        {
            // If character is not a number...
            if ( !Char.IsDigit(charValue) )
            {
                // Cancel the event
                e.Cancel = true;
                break;
            } // If character is not a number...
        } // Loop to validate text...
    } // If not cancelling and not deleting...

    // Notify other subscribers
    base.OnTextChanging(e);
}

Alternatively, it is possible to simply subscribe to the TextChanging event. An example of this approach is provided via the alphabeticTextBox_TextChanging method in FormMain. Since the code is nearly identical to the previous example, it is not shown here.

In each of these examples the TextChangingEventArgs class is used to convey information about the TextChanging event. It contains the following members...

Name Type Description
Cancel bool If set to true, the proposed changes to the Text property will be cancelled.
IsAssign boolIf true, the event is associated with assignment to the Text property.
IsDeleteboolIf true, the event is associated with deletion of characters.
IsInsertboolIf true, the event is associated with insertion of characters.
AfterTextstringProposed value of Text property if event is not canceled.
BeforeTextstringOriginal value of Text property prior to event.
InsertTextstringIf IsInsert is true, contains the text that is being inserted; otherwise, it contains the value null.
TypeTextChangingTypeThe type of operation that caused the TextChanging event.
BeforeRemoveStartintThe index of the first character, in the original text, that is being removed or replaced. If IsInsert is true, it also specifies the index, in the original text, at which characters will be inserted.
BeforeRemoveLengthintThe number of characters, in the original text, that are being removed or replaced.

TextChangingType is simply an enumeration of all the operations that can cause a TextChanging event. They fall into three categories: assignment (see IsAssign), deletion (see IsDelete), and insertion (see IsInsert). The only assignment type is Assign. The deletion types are: Backspace, Clear, and Cut. The insertion types are: KeyPress and Paste.

Implementation

The main challenge in implementing the FilterTextBox was identifying all of sources of text change for the TextBox control. Once each of these was identified, it was necessary to discover a mechanism for intercepting each change and canceling it.

To this end, I created a table for each source of change I could find. These fell into four categories: the context menu for the TextBox, keyboard input, methods of the TextBox control, and properties of the TextBox control.

Keyboard input is the most obvious source of change, since this is what the control is designed to filter. All non-control characters are intercepted by overriding the OnKeyPress method. A TextChanging event of type TextChangingType.KeyPress is fired for each keystroke. If the event is canceled, by one of the subscribers, the key stroke is discarded by setting the KeyPressEventArgs.Handled to true.

The backspace and delete key are similarly intercepted and canceled. For operations like Clear, Cut, and Paste; overriding the WndProc method to intercept the corresponding Windows message seemed the most economical solution. While not pure .NET, it was the only practical means I could identify for transparently trapping the context menu operations.

All sources of change, except non-control key strokes, are detailed in the table below...

CategoryNameInterceptTextChangingType
Context MenuDeleteFilterTextBox.WndProc()Clear
Context MenuCutFilterTextBox.WndProc()Cut
Context MenuPasteFilterTextBox.WndProc()Paste
Keyboard InputDeleteFilterTextBox.OnKeyDown()Clear
Keyboard InputShift+DeleteFilterTextBox.WndProc()Cut
Keyboard InputControl+XFilterTextBox.WndProc()Cut
Keyboard InputShift+InsertFilterTextBox.WndProc()Paste
Keyboard InputControl+VFilterTextBox.WndProc()Paste
Keyboard InputBackspaceFilterTextBox.OnKeyPress()Backspace
MethodTextBox.AppendText()n/an/a
MethodTextBox.Clear()FilterTextBox.TextAssignment
MethodTextBox.Cut()FilterTextBox.WndProc()Cut
MethodTextBox.Paste()FilterTextBox.WndProc()Paste
MethodTextBox.ResetText()FilterTextBox.TextAssignment
PropertyTextBox.TextFilterTextBox.TextAssignment

Regrettably, I could not identify a means to intercept and cancel changes from the TextBox.AppendText() method. It can not be overridden and does not assign to the Text property to change its value. While this is unfortunate, it is unlikely to affect most applications.

Conclusions

Given the plethora of other postings on this subject, I hesitated to post this article. However, none of the solutions I found in a quick search aspired to be a general purpose base class for TextBox filtering. Instead each seemed to be narrowly targeted at solving a specific filtering need (for example, a numeric TextBox).

References

  • TextBox class (MSDN), http://msdn2.microsoft.com/en-us/library/system.windows.forms.textbox.aspx

    Revision History

    03-17-2007

  • Original article.
  • 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

    Share

    About the Author

    Eric Lynch
    Software Developer
    United States United States
    No Biography provided

    Comments and Discussions

     
    QuestionPlagarism? Pinmemberveritas guy7-May-08 15:35 
    AnswerRe: Plagarism? [modified] PinmemberEric Lynch16-Dec-08 15:17 
    GeneralThanks! PinmemberSteve9879624-Oct-07 5:12 
    GeneralRe: Thanks! PinmemberEric Lynch25-Oct-07 14:34 
    GeneralI wonder if were related :p PinmemberEnnis Ray Lynch, Jr.20-Mar-07 13:27 
    GeneralRe: I wonder if were related :p PinmemberEric Lynch20-Mar-07 14:14 

    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 | Terms of Use | Mobile
    Web04 | 2.8.150327.1 | Last Updated 20 Mar 2007
    Article Copyright 2007 by Eric Lynch
    Everything else Copyright © CodeProject, 1999-2015
    Layout: fixed | fluid