views:

1790

answers:

5

What is the best way to block certain input keys from being used in a TextBox with out blocking special keystrokes such as Ctrl-V/Ctrl-C?

For example, only allowing the user to enter a subset of characters or numerics such as A or B or C and nothing else.

A: 

You could use the TextChanged event for the textbox.

    private void txtInput_TextChanged(object sender, EventArgs e)
    {
        if (txtInput.Text.ToUpper() == "A" || txtInput.Text.ToUpper() == "B")
        {
            //invalid entry logic here
        }
    }
Nathan Koop
Sorry, but that is pretty ugly.
Ed Swangren
+2  A: 

I used the Masked Textbox control for winforms. There's a longer explanation about it here. Essentially, it disallows input that doesn't match the criteria for the field. If you didn't want people to type in anything but numbers, it simply would not allow them to type anything but numbers.

George Stocker
+1  A: 

I would use the keydown-event and use the e.cancel to stop the key if the key is not allowed. If I want to do it on multiple places then I would make a user control that inherits a textbox and then add a property AllowedChars or DisallowedChars that handle it for me. I have a couple of variants laying around that I use for time to time, some allowing money-formatting and input, some for time editing and so on.

The good thing to do it as a user control is that you can add to it and make it to your own killer-text-box. ;)

Stefan
+2  A: 

This is how I handle this usually.

Regex regex = new Regex("[0-9]|\b");            
e.Handled = !(regex.IsMatch(e.KeyChar.ToString()));

That will only allow numerical characters and the backspace. The problem is that you will not be allowed to use control keys in this case. I would create my own textbox class if you want to keep that functionality.

Ed Swangren
Ed: I am already doing this with Regex's, and need to extend textbox to allow ctrl keys. I am handling Backspace and Delete as special cases in the KeyPress event, is the KeyPress event the correct place do do the key checks/blocks
benPearce
+1  A: 

I found the only working solution ended being doing a pre-check of the keypress in the ProcessCmdKey for Ctrl-V,Ctrl-C, Delete or Backspace, and the doing a further validation if it was not one of these keys in the KeyPress event by using a regular expression.

This is probably not the best way but it worked in my circumstance.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    // check the key to see if it should be handled in the OnKeyPress method
    // the reasons for doing this check here is:
    // 1. The KeyDown event sees certain keypresses differently, e.g NumKeypad 1 is seen as a lowercase A
    // 2. The KeyPress event cannot see Modifer keys so cannot see Ctrl-C,Ctrl-V etc.
    // The functionality of the ProcessCmdKey has not changed, it is simply doing a precheck before the 
    // KeyPress event runs
    switch (keyData)
    {
        case Keys.V | Keys.Control :
        case Keys.C | Keys.Control :
        case Keys.X | Keys.Control :
        case Keys.Back :
        case Keys.Delete :
            this._handleKey = true;
            break;
        default:
            this._handleKey = false;
            break;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}


protected override void OnKeyPress(KeyPressEventArgs e)
{
    if (String.IsNullOrEmpty(this._ValidCharExpression))
    {
        this._handleKey = true;
    }
    else if (!this._handleKey)
    {
        // this is the final check to see if the key should be handled
        // checks the key code against a validation expression and handles the key if it matches
        // the expression should be in the form of a Regular Expression character class
        // e.g. [0-9\.\-] would allow decimal numbers and negative, this does not enforce order, just a set of valid characters
        // [A-Za-z0-9\-_\@\.] would be all the valid characters for an email
        this._handleKey = Regex.Match(e.KeyChar.ToString(), this._ValidCharExpression).Success;
    }
    if (this._handleKey)
    {
        base.OnKeyPress(e);
        this._handleKey = false;
    }
    else
    {
        e.Handled = true;
    }

}
benPearce