views:

8267

answers:

9

I have a windows forms app with a textbox control that I want to only accept integer values. In the past I've done this kind of validation by overloading the KeyPress event and just removing characters which didn't fit the specification. I've looked at the MaskedTextBox control but I'd like a more general solution that could work with perhaps a regular expression, or depend on the values of other controls.

Ideally this would behave such that pressing a non numeric character would either produce no result or immediately provide the user with feedback about the invalid character.

A: 

you could use TextChanged/ Keypress event, use a regex to filter on numbers and take some action.

Perpetualcoder
A: 

Try a MaskedTextBox. It takes a simple mask format so you can limit the input to numbers or dates or whatever.

Andrew Kennan
I specifically do not want to use a MaskedTextBox. The formats they allow can be very limiting. They work for this case but I'd like to do something more general.
Mykroft
Sorry - didn't read your question properly :]
Andrew Kennan
+3  A: 

I am assuming from context and the tags you used that you are writing a .NET C# app. In this case, you can subscribe to the text changed event, and validate each key stroke.

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch("[^0-9]", textBox1.Text))
        {
            MessageBox.Show("Please enter only numbers.");
            textBox1.Text.Remove(textBox1.Text.Length - 1);
        }
    }
Anthony D
Isn't that going to give a very weird effect if you type into the middle of a number?
Colin Pickard
+14  A: 

Two options:

  1. Use a NumericUpDown instead. NumericUpDown does the filtering for you, which is nice. Of course it also gives your users the ability to hit the up and down arrows on the keyboard to increment and decrement the current value.

  2. Handle the appropriate keyboard events to prevent anything but numeric input. I've had success with this two event handlers on a standard TextBox:

(Inserting a line here because the markdown preview doesn't like a code sample immediately following an ordered list. Weird.)

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!char.IsControl(e.KeyChar) 
        && !char.IsDigit(e.KeyChar) 
        && e.KeyChar != '.')
    {
        e.Handled = true;
    }

    // only allow one decimal point
    if (e.KeyChar == '.' 
        && (sender as TextBox).Text.IndexOf('.') > -1)
    {
        e.Handled = true;
    }
}

You can remove the check for '.' (and the subsequent check for more than one '.') if your TextBox shouldn't allow decimal places. You could also add a check for '-' if your TextBox should allow negative values.

Matt Hamilton
I'd forgotten the numeric up down control exists. It's actually what I should be using here instead of a textbox. In the future when I have more complicated validation I'll used the handled property with the KeyPress event.
Mykroft
The only drawback with NumericUpDown is that it provides no feedback when you enter a value outside of the Maximum or Minimum allowed values - it just changes what you've typed. A TextBox can at least allow invalid values so you can warn the user when they submit the form.
Matt Hamilton
It is also possible to get values into a textbox with just the mouse
GvS
That's true - the user could always paste in some non-numeric characters. You would hope that the form validation would catch that though, since at some point you're gonna want to do an Int32.TryParse or something.
Matt Hamilton
You'll need some addition effort to globalize this by replacing checks for '.' with checks on CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.
Jeff Yates
A: 

Take a look at http://stackoverflow.com/questions/294611/input-handling-in-winform

I have posted my solution which uses the ProcessCmdKey and OnKeyPress events on the textbox. The comments show you how to use a Regex to verify the keypress and block/allow appropriatly.

benPearce
+1  A: 

I have made something for this on CodePlex.

It works by intercepting the TextChanged event. If the result is a good number it will be stored. If it is something wrong, the last good value will be restored. The source is a bit too large to publish here, but here is a link to the class that handles the core of this logic.

GvS
+2  A: 

And just because it's always more fun to do stuff in one line...

 private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
    }

NOTE: This DOES NOT prevent a user from Copy / Paste into this textbox. It's not a fail safe way to sanitize your data.

BFree
A: 

When i click the textbox , i am getting as private void textBox1_TextChanged(object sender, EventArgs e) { }

But how u r getting like

private void textBox1_KeyPress(object sender, KeyPressEventArgs e) {

}
ivreddy
A: 

We can mask the textBox to text only by the following mechanism

    private void txtName_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsLetter(e.KeyChar) && !char.IsControl(e.KeyChar))
        {
            e.Handled = true;
        }
    }
Ramesh
-1 for giving the same answer one and a half year later.
Oliver