672

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.

Mykroft
  • 13,077
  • 13
  • 44
  • 72

41 Answers41

920

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:

    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.

If you want to limit the user for number of digit, use: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits

Bitterblue
  • 13,162
  • 17
  • 86
  • 124
Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • 2
    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 Jan 20 '09 at 22:11
  • 8
    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 Jan 20 '09 at 22:12
  • 1
    It is also possible to get values into a textbox with just the mouse – GvS Jan 20 '09 at 22:24
  • 7
    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 Jan 20 '09 at 22:41
  • 57
    You'll need some addition effort to globalize this by replacing checks for '.' with checks on CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator. – Jeff Yates Apr 16 '09 at 18:08
  • 1
    @Matt, why do you care about the Control key? `if (!char.IsControl(e.KeyChar)` – Hamish Grubijan Aug 10 '11 at 16:42
  • @Hamish if the user is hitting Ctrl+3, I know I don't need to continue. – Matt Hamilton Aug 10 '11 at 20:55
  • 8
    @HamishGrubijan, IsControl has nothing to do with the Control key; it returns whether or not a char is a control char. By allowing control chars, you don't break things like backspace, delete or the arrow keys – Thomas Levesque Oct 31 '11 at 02:22
  • 1
    Is it `TextChanged()` now instead of `KeyPress()`? – SearchForKnowledge Apr 13 '15 at 17:43
  • This is useful as an extension too. – Jack Jul 01 '15 at 20:52
  • 19
    This still accepts illegal ctrl+v input, by the way; a bug which even exists in the official NumericUpDown control. – Nyerguds Aug 10 '15 at 22:33
  • 1
    Seems like this code accepts 123-456 as a valid input. We should also consider the index at which - is placed – Ramu Feb 29 '16 at 12:23
  • may be we can change code From : // only allow one decimal point ` if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1)) { e.Handled = true; } to : // only allow one decimal point only in the beginning if (e.KeyChar == '-') { if ((sender as TextBox).Text.IndexOf('-') > -1) return true; if ((sender as TextBox).Text.Length > 0) return true; }` – Ramu Feb 29 '16 at 12:53
  • 1
    You can set numericUpDown ReadOnly. Then you can only increment/decrement with arrows. Paste will not work – Koxo Dec 07 '18 at 06:34
  • Just keep in mind that the numericUpDown.Value is decimal and has a different range than float or double (±1.5 x E−45 to ±3.4 x E38 and ±5.0 × E−324 to ±1.7 × E308, respectively) compared to that of decimal type (±1.0 x E-28 to ±7.9228 x E28). So, if you need very large or very small numbers, numericUpDown may not be suitable. – m_a_s Jan 15 '19 at 01:41
  • works, but there's an error when I paste something with control + v, letters are still added. – Eduardo Herrera Oct 23 '20 at 22:00
  • @EduardoHerrera you can use `onChange` event i guess to prevent `ctrl+v` by clearing the entire text or do whatever. Though I think numericUpDown is kinda ugly if you need to accept some big numbers. – Shahaboddin Mar 24 '22 at 02:00
184

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
  • 102,548
  • 21
  • 159
  • 201
  • this is not a general solutions as it works only for intergers. I had to implement such thing recently and i ended up with try-parsing resulting string to number and allowing input only if parsing succeeded – grzegorz_p Jan 04 '12 at 15:03
  • 1
    This may not work when multiple methods handle `KeyPress` events from the same text box. One event might set `e.Handled` to true, and then another could set it back to false. In general, it's better to use `if (...) e.Handled = true;` – Nathaniel Jones May 27 '14 at 16:55
  • 2
    You can disable ShortcutsEnabled property to prevent copy paste by keyboard or menu – Ahmad Dec 11 '14 at 13:25
  • 3
    Eh. A `TextChanged` event that goes over it with a regex can fix copy-paste ;) – Nyerguds Aug 10 '15 at 22:34
  • 1st: The one liner CAN prevent copy/paste if you fix the bug in it (`&& !` must be a `||`). 2nd: You can fix it, so that it prevents only paste and yet allows copy/cut/select all. – Bitterblue Mar 20 '20 at 09:18
  • for the paste issue, I just overrided the `WndProc` method, and ignore it (paste code = 0x0302) if it contains non digits: string text = Text; PasteEventArgs e = new PasteEventArgs(text, Clipboard.GetText(), SelectionStart, SelectionLength); TextPasted(this, e); if (!e.Handled && text.Equals(Text)) Text = text.Substring(0, e.SelectionStart) + e.PastedText + text.Substring(e.SelectionStart + e.SelectionLength); – Guiorgy Sep 29 '20 at 16:11
59

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(textBox1.Text, "[^0-9]"))
    {
        MessageBox.Show("Please enter only numbers.");
        textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
    }
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Anthony D
  • 10,877
  • 11
  • 46
  • 67
  • 30
    Isn't that going to give a very weird effect if you type into the middle of a number? – Colin Pickard Oct 25 '10 at 19:14
  • 5
    and also it should be: `textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);` – Pieniadz Aug 24 '11 at 09:59
  • 3
    what if the first character itself is not a digit...wouldn't subtracting 1 in that case throw an error.... – manu_dilip_shah Mar 26 '12 at 08:29
  • 7
    Also, using TextChanged instead of KeyPress creates a bit of recursion in that the code will jump into a second TextChanged event after the Remove method. – WEFX May 21 '13 at 14:29
  • 2
    You switched input and pattern parameters for your IsMatch function. Input should be first, then pattern. http://msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx – Mibou Feb 17 '14 at 09:52
  • 1
    The remove will remove all the text rather than the invalid char. I think it will be better to store the previous valid change and update accordingly. – eracube Jun 27 '18 at 10:42
  • resolve the problem with TextChangedEventArgs and use e.Changes -> Change.Offset – Lenor Sep 05 '19 at 14:14
40

Here is a simple standalone Winforms custom control, derived from the standard TextBox, that allows only System.Int32 input (it could be easily adapted for other types such as System.Int64, etc.). It supports copy/paste operations and negative numbers:

public class Int32TextBox : TextBox
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        base.OnKeyPress(e);

        NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;

        string c = e.KeyChar.ToString();
        if (char.IsDigit(c, 0))
            return;

        if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
            return;

        // copy/paste
        if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
            && ((ModifierKeys & Keys.Control) == Keys.Control))
            return;

        if (e.KeyChar == '\b')
            return;

        e.Handled = true;
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        const int WM_PASTE = 0x0302;
        if (m.Msg == WM_PASTE)
        {
            string text = Clipboard.GetText();
            if (string.IsNullOrEmpty(text))
                return;

            if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
                return;

            int i;
            if (!int.TryParse(text, out i)) // change this for other integer types
                return;

            if ((i < 0) && (SelectionStart != 0))
                return;
        }
        base.WndProc(ref m);
    }

Update 2017: My first answer has some issues:

  • you can type something that's longer than an integer of a given type (for example 2147483648 is greater than Int32.MaxValue);
  • more generally, there's no real validation of the result of what has been typed;
  • it only handles int32, you'll have to write specific TextBox derivated control for each type (Int64, etc.)

So I came up with another version that's more generic, that still supports copy/paste, + and - sign, etc.

public class ValidatingTextBox : TextBox
{
    private string _validText;
    private int _selectionStart;
    private int _selectionEnd;
    private bool _dontProcessMessages;

    public event EventHandler<TextValidatingEventArgs> TextValidating;

    protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (_dontProcessMessages)
            return;

        const int WM_KEYDOWN = 0x100;
        const int WM_ENTERIDLE = 0x121;
        const int VK_DELETE = 0x2e;

        bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
        if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
        {
            DontProcessMessage(() =>
            {
                _validText = Text;
                _selectionStart = SelectionStart;
                _selectionEnd = SelectionLength;
            });
        }

        const int WM_CHAR = 0x102;
        const int WM_PASTE = 0x302;
        if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
        {
            string newText = null;
            DontProcessMessage(() =>
            {
                newText = Text;
            });

            var e = new TextValidatingEventArgs(newText);
            OnTextValidating(this, e);
            if (e.Cancel)
            {
                DontProcessMessage(() =>
                {
                    Text = _validText;
                    SelectionStart = _selectionStart;
                    SelectionLength = _selectionEnd;
                });
            }
        }
    }

    private void DontProcessMessage(Action action)
    {
        _dontProcessMessages = true;
        try
        {
            action();
        }
        finally
        {
            _dontProcessMessages = false;
        }
    }
}

public class TextValidatingEventArgs : CancelEventArgs
{
    public TextValidatingEventArgs(string newText) => NewText = newText;
    public string NewText { get; }
}

For Int32, you can either derive from it, like this:

public class Int32TextBox : ValidatingTextBox
{
    protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
    {
        e.Cancel = !int.TryParse(e.NewText, out int i);
    }
}

or w/o derivation, use the new TextValidating event like this:

var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);

but what's nice is it works with any string, and any validation routine.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • This is great, nice and simple, easily used, and deals with unusual input attempts. Thanks! – WiredEarp Sep 28 '15 at 05:14
  • 1
    Note on the 2017 version, when there is one value e.g. 1 and you hit backspace it's ignored while if you had say 120 and hit backspace three times we are left with 1. – Karen Payne Dec 02 '17 at 14:04
  • 1
    Your ValidatingTextbox is by far on of the best implementation I've seen for a while. Simple and effective. Thanks! – Samuel Sep 11 '19 at 20:28
  • How can I implement it in my project 2019? – Eduardo Herrera Oct 24 '20 at 21:48
  • Could you make this work for TextBox with multiline true? I want to allow positive doubles on multiple lines – Steve W Sep 16 '21 at 14:16
  • @SteveW - just update the `OnTextValidating` method the way you like, eg: `e.Cancel = !int.TryParse(e.NewText.Replace(Environment.NewLine, string.Empty), out int i);` should support multiline – Simon Mourier Sep 16 '21 at 14:45
  • I can see how that code will work for int (as you seem to be concatenating the ints into a single int) but not for double due to multiple fullstops/periods? – Steve W Sep 16 '21 at 14:51
  • 1
    @SteveW - depending on how you want to do it, you'll have to write some code to do validation yes. – Simon Mourier Sep 16 '21 at 15:26
28

This is exactly what the Validated/Validating events were designed for.

Here's the MSDN article on the topic: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

The TL;DR version: check the .Text property in the Validating event and set e.Cancel=True when the data is invalid.

When you set e.Cancel=True, the user can't leave the field, but you will need to give them some kind of feedback that something's wrong. I change the box's background color to light red to indicate a problem. Make sure to set it back to SystemColors.Window when Validating is called with a good value.

TomXP411
  • 899
  • 9
  • 14
  • 2
    +1 for mentioning a very API-idiomatic approach. I'm relatively new to Windows Forms, and it's quite a jungle of functionality & MSDN docs, so also thanks for the specific doc pointer to `Validating`. ``The OP mentions that immediately disallowing/indicating an invalidating character is ideal, but `Validating` seems to require that focus be moved to another form/control before it takes effect.`` Still, this is a great approach and always worth considering in the more general case. – William Jul 23 '14 at 15:37
  • This is a great solution as minimal implementation is required. It is worth noting that the Validating event only occurs when the control loses focus. However, it is easy enough to call the same validation function from keypress to get live validation. – Ashley Duncan Apr 21 '21 at 23:04
14

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

Andrew Kennan
  • 13,947
  • 3
  • 24
  • 33
  • 3
    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 Jan 20 '09 at 22:03
13

You can use the TextChanged event

private void textBox_BiggerThan_TextChanged(object sender, EventArgs e)
{
    long a;
    if (! long.TryParse(textBox_BiggerThan.Text, out a))
    {
        // If not int clear textbox text or Undo() last operation
        textBox_LessThan.Clear();
    }
}
default
  • 11,485
  • 9
  • 66
  • 102
Davit Tvildiani
  • 1,915
  • 3
  • 19
  • 29
  • Looks like it should work well if you used `Undo()`, but it results in an `StackOverflowException`. – Drew Chapin Oct 19 '15 at 03:44
  • It looks like the TextChanged propery is part of routine that you wanna undo(). I have variable for the whole window and I am using `public int txtBoxValue`, and if tryParse doesn't work, I revert text in txtBox by `txtBox.Text = txtBoxValue.ToString();` – L. Zeda Dec 22 '16 at 08:41
9

Just use a NumericUpDown control and set those ugly up down buttons visibility to false.

numericUpDown1.Controls[0].Visible = false;

NumericUpDown is actually a collection of controls containing a 'spin box' (up down buttons), a text box and some code to validate and wange-jangle it all together.

Marking:

YourNumericUpDown.Controls[0].visible = false 

will hide the buttons while keeping the underlying code active.

While not being an obvious solution it is simple and effective. .Controls[1] would hide the text box portion if you wanted to do that instead.

Dean Seo
  • 5,486
  • 3
  • 30
  • 49
user2163234
  • 527
  • 5
  • 9
  • The accepted answer did not include any information on how to remove the up down buttons, how to do so is not obvious as there are no human readable interfaces to enable or disable them. NumericUpDown is actually a collection of controls containing a text box and a "spin box" (up down buttons) and some code handling input validation. – user2163234 Nov 27 '17 at 23:19
8

This might be useful. It allows "real" numeric values, including proper decimal points and preceding plus or minus signs. Call it from within the related KeyPress event.

       private bool IsOKForDecimalTextBox(char theCharacter, TextBox theTextBox)
    {
        // Only allow control characters, digits, plus and minus signs.
        // Only allow ONE plus sign.
        // Only allow ONE minus sign.
        // Only allow the plus or minus sign as the FIRST character.
        // Only allow ONE decimal point.
        // Do NOT allow decimal point or digits BEFORE any plus or minus sign.

        if (
            !char.IsControl(theCharacter)
            && !char.IsDigit(theCharacter)
            && (theCharacter != '.')
            && (theCharacter != '-')
            && (theCharacter != '+')
        )
        {
            // Then it is NOT a character we want allowed in the text box.
            return false;
        }



        // Only allow one decimal point.
        if (theCharacter == '.'
            && theTextBox.Text.IndexOf('.') > -1)
        {
            // Then there is already a decimal point in the text box.
            return false;
        }

        // Only allow one minus sign.
        if (theCharacter == '-'
            && theTextBox.Text.IndexOf('-') > -1)
        {
            // Then there is already a minus sign in the text box.
            return false;
        }

        // Only allow one plus sign.
        if (theCharacter == '+'
            && theTextBox.Text.IndexOf('+') > -1)
        {
            // Then there is already a plus sign in the text box.
            return false;
        }

        // Only allow one plus sign OR minus sign, but not both.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && 
            (
                (theTextBox.Text.IndexOf('-') > -1)
                ||
                (theTextBox.Text.IndexOf('+') > -1)
            )
            )
        {
            // Then the user is trying to enter a plus or minus sign and
            // there is ALREADY a plus or minus sign in the text box.
            return false;
        }

        // Only allow a minus or plus sign at the first character position.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && theTextBox.SelectionStart != 0
            )
        {
            // Then the user is trying to enter a minus or plus sign at some position 
            // OTHER than the first character position in the text box.
            return false;
        }

        // Only allow digits and decimal point AFTER any existing plus or minus sign
        if  (
                (
                    // Is digit or decimal point
                    char.IsDigit(theCharacter)
                    ||
                    (theCharacter == '.')
                )
                &&
                (
                    // A plus or minus sign EXISTS
                    (theTextBox.Text.IndexOf('-') > -1)
                    ||
                    (theTextBox.Text.IndexOf('+') > -1)
                )
                &&
                    // Attempting to put the character at the beginning of the field.
                    theTextBox.SelectionStart == 0
            )
        {
            // Then the user is trying to enter a digit or decimal point in front of a minus or plus sign.
            return false;
        }

        // Otherwise the character is perfectly fine for a decimal value and the character
        // may indeed be placed at the current insertion position.
        return true;
    }
Roger Garrett
  • 349
  • 1
  • 7
  • 13
6

I've been working on a collection of components to complete missing stuff in WinForms, here it is: Advanced Forms

In particular this is the class for a Regex TextBox

/// <summary>Represents a Windows text box control that only allows input that matches a regular expression.</summary>
public class RegexTextBox : TextBox
{
    [NonSerialized]
    string lastText;

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public virtual Regex Regex { get; set; }

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [DefaultValue(null)]
    [Category("Behavior")]
    [Description("Sets the regular expression governing the input allowed for this control.")]
    public virtual string RegexString {
        get {
            return Regex == null ? string.Empty : Regex.ToString();
        }
        set {
            if (string.IsNullOrEmpty(value))
                Regex = null;
            else
                Regex = new Regex(value);
        }
    }

    protected override void OnTextChanged(EventArgs e) {
        if (Regex != null && !Regex.IsMatch(Text)) {
            int pos = SelectionStart - Text.Length + (lastText ?? string.Empty).Length;
            Text = lastText;
            SelectionStart = Math.Max(0, pos);
        }

        lastText = Text;

        base.OnTextChanged(e);
    }
}

Simply adding something like myNumbericTextBox.RegexString = "^(\\d+|)$"; should suffice.

Fabio Iotti
  • 1,480
  • 1
  • 16
  • 20
5

simply use this code in textbox :

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

    if (!double.TryParse(textBox1.Text, out parsedValue))
    {
        textBox1.Text = "";
    }
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
saurabh27
  • 61
  • 1
  • 7
5

Both integers and floats need to be accepted, including the negative numbers.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // Text
    string text = ((Control) sender).Text;

    // Is Negative Number?
    if (e.KeyChar == '-' && text.Length == 0)
    {
        e.Handled = false;
        return;
    }

    // Is Float Number?
    if (e.KeyChar == '.' && text.Length > 0 && !text.Contains("."))
    {
        e.Handled = false;
        return;
    }

    // Is Digit?
    e.Handled = (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar));
}
plamut
  • 3,085
  • 10
  • 29
  • 40
Hadi Akbarzadeh
  • 750
  • 10
  • 18
4

In our webpage with the definition of textbox we can add an onkeypress event for accepting only numbers. It will not show any message but it will prevent you from wrong input. It worked for me, user could not enter anything except number.

<asp:TextBox runat="server" ID="txtFrom"
     onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
ssah
  • 119
  • 3
4

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
  • 52,015
  • 16
  • 101
  • 139
3

This is my aproach:

  1. using linq (easy to modify filter)
  2. copy/paste proof code
  3. keeps caret position when you press a forbidden character
  4. accepts left zeroes
  5. and any size numbers

    private void numeroCuenta_TextChanged(object sender, EventArgs e)
    {
        string org = numeroCuenta.Text;
        string formated = string.Concat(org.Where(c => (c >= '0' && c <= '9')));
        if (formated != org)
        {
            int s = numeroCuenta.SelectionStart;
            if (s > 0 && formated.Length > s && org[s - 1] != formated[s - 1]) s--;
            numeroCuenta.Text = formated;
            numeroCuenta.SelectionStart = s;
        }
    }
    
Ing. Gerardo Sánchez
  • 1,607
  • 15
  • 14
3

This is a nice and short way to do it with .NET 5/Core

private void textBox1_KeyDown(object sender, KeyEventArgs e) {
  if (e.KeyData != Keys.Back)
    e.SuppressKeyPress = !int.TryParse(Convert.ToString((char) e.KeyData), out int _);
}

Edit: Added support for backspace key

Kye
  • 76
  • 1
  • 10
  • I'm looking for a way to allow positive ints/doubles in a multiline TextBox. Can your method do this? – Steve W Sep 16 '21 at 14:05
2

I would handle it in the KeyDown event.

void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            char c = Convert.ToChar(e.PlatformKeyCode);
            if (!char.IsDigit(c))
            {
                e.Handled = true;
            }
        }
Shaz
  • 2,676
  • 1
  • 22
  • 22
  • 2
    What about Keys like "Backspace", "Delete", "Arrow-Key-Left", "Arrow-Key-Right", Copy and Paste, Digits entered by Numpad (they are traded as !digit) – user799821 May 27 '13 at 10:19
  • Just add a few more tests like this: if (!char.IsDigit(c) && c != (char)Keys.Back) – dnennis Dec 29 '15 at 10:59
2
private void txt3_KeyPress(object sender, KeyPressEventArgs e)
{
    for (int h = 58; h <= 127; h++)
    {
        if (e.KeyChar == h)             //58 to 127 is alphabets tat will be         blocked
        {
            e.Handled = true;
        }
    }
    for(int k=32;k<=47;k++)
    {
        if (e.KeyChar == k)              //32 to 47 are special characters tat will 
        {                                  be blocked
            e.Handled = true;
        }
    }
}

try this is very simple

Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
rithish
  • 131
  • 1
  • 6
2

Hi you can do something like this in the textchanged event of the textbox.

here is a demo

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        string actualdata = string.Empty;
        char[] entereddata = textBox1.Text.ToCharArray();
        foreach (char aChar in entereddata.AsEnumerable())
        {
            if (Char.IsDigit(aChar))
            {
                actualdata = actualdata + aChar;
                // MessageBox.Show(aChar.ToString());
            }
            else
            {
                MessageBox.Show(aChar + " is not numeric");
                actualdata.Replace(aChar, ' ');
                actualdata.Trim();
            }
        }
        textBox1.Text = actualdata;
    }
Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62
2

It seems like many of the current answers to this question are manually parsing the input text. If you're looking for a specific built-in numeric type (e.g. int or double), why not just delegate the work to that type's TryParse method? For example:

public class IntTextBox : TextBox
{
    string PreviousText = "";
    int BackingResult;

    public IntTextBox()
    {
        TextChanged += IntTextBox_TextChanged;
    }

    public bool HasResult { get; private set; }

    public int Result
    {
        get
        {
            return HasResult ? BackingResult : default(int);
        }
    }

    void IntTextBox_TextChanged(object sender, EventArgs e)
    {
        HasResult = int.TryParse(Text, out BackingResult);

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

If you want something more generic but still compatible with Visual Studio's Designer:

public class ParsableTextBox : TextBox
{
    TryParser BackingTryParse;
    string PreviousText = "";
    object BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out object result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public object Result
    {
        get
        {
            return GetResult<object>();
        }
    }

    public T GetResult<T>()
    {
        return HasResult ? (T)BackingResult : default(T);
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

And finally, if you want something fully generic and don't care about Designer support:

public class ParsableTextBox<T> : TextBox
{
    TryParser BackingTryParse;
    string PreviousText;
    T BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out T result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public T Result
    {
        get
        {
            return HasResult ? BackingResult : default(T);
        }
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}
William
  • 1,993
  • 2
  • 23
  • 40
2

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

Perpetualcoder
  • 13,501
  • 9
  • 64
  • 99
2

Take a look at 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 appropriately.

Community
  • 1
  • 1
benPearce
  • 37,735
  • 14
  • 62
  • 96
2

Using the approach described in Fabio Iotti's answer I have created a more generic solution:

public abstract class ValidatedTextBox : TextBox {
    private string m_lastText = string.Empty;
    protected abstract bool IsValid(string text);
    protected sealed override void OnTextChanged(EventArgs e) {
        if (!IsValid(Text)) {
            var pos = SelectionStart - Text.Length + m_lastText.Length;
            Text = m_lastText;
            SelectionStart = Math.Max(0, pos);
        }
        m_lastText = Text;
        base.OnTextChanged(e);
    }
}

"ValidatedTextBox", which contains all nontrivial validation behavior. All that's left to do is inherit from this class and override "IsValid" method with whatever validation logic is required. For example, using this class, it is possible to create "RegexedTextBox" which will accept only strings which match specific regular expression:

public abstract class RegexedTextBox : ValidatedTextBox {
    private readonly Regex m_regex;
    protected RegexedTextBox(string regExpString) {
        m_regex = new Regex(regExpString);
    }
    protected override bool IsValid(string text) {
        return m_regex.IsMatch(Text);
    }
}

After that, inheriting from the "RegexedTextBox" class, we can easily create "PositiveNumberTextBox" and "PositiveFloatingPointNumberTextBox" controls:

public sealed class PositiveNumberTextBox : RegexedTextBox {
    public PositiveNumberTextBox() : base(@"^\d*$") { }
}

public sealed class PositiveFloatingPointNumberTextBox : RegexedTextBox {
    public PositiveFloatingPointNumberTextBox()
        : base(@"^(\d+\" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + @")?\d*$") { }
}
PolarBear
  • 1,117
  • 15
  • 24
1

This one works with copy and paste, drag and drop, key down, prevents overflow and is pretty simple

public partial class IntegerBox : TextBox 
{
    public IntegerBox()
    {
        InitializeComponent();
        this.Text = 0.ToString();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    private String originalValue = 0.ToString();

    private void Integerbox_KeyPress(object sender, KeyPressEventArgs e)
    {
        originalValue = this.Text;
    }

    private void Integerbox_TextChanged(object sender, EventArgs e)
    {
        try
        {
            if(String.IsNullOrWhiteSpace(this.Text))
            {
                this.Text = 0.ToString();
            }
            this.Text = Convert.ToInt64(this.Text.Trim()).ToString();
        }
        catch (System.OverflowException)
        {
            MessageBox.Show("Value entered is to large max value: " + Int64.MaxValue.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.Text = originalValue;
        }
        catch (System.FormatException)
        {                
            this.Text = originalValue;
        }
        catch (System.Exception ex)
        {
            this.Text = originalValue;
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK , MessageBoxIcon.Error);
        }
    }       
}
1

I was also looking for the best way to check only numbers in textbox and problem with keypress was it does not support copy paste by right click or clipboard so came up with this code which validates the when cursor leaves the text field and also it checks for empty field. (adapted version of newguy)

private void txtFirstValue_MouseLeave(object sender, EventArgs e)
{
    int num;
    bool isNum = int.TryParse(txtFirstValue.Text.Trim(), out num);

    if (!isNum && txtFirstValue.Text != String.Empty)
    {
        MessageBox.Show("The First Value You Entered Is Not a Number, Please Try Again", "Invalid Value Detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtFirstValue.Clear();
    }
}
Dean Seo
  • 5,486
  • 3
  • 30
  • 49
Alston Antony
  • 179
  • 2
  • 13
  • MouseLeave seems like a really bad choice for an event to use. – LarsTech Oct 08 '15 at 20:20
  • @LarsTech what I thought was textchanged even can causes error messagebox before even if user realizes error and try to fix it so I thought I would work better. What do you think is the best event for this case ? – Alston Antony Oct 08 '15 at 21:00
  • @AlstonAntony late comment, i know. But a simple click event that activates on rightclick would suffice wouldnt it? – Takarii May 03 '16 at 07:41
1

Do not forget that a user can paste an invalid text in a TextBox.

If you want to restrict that, follow the below code:

private void ultraTextEditor1_TextChanged(object sender, EventArgs e)
{
    string append="";
    foreach (char c in ultraTextEditor1.Text)
    {
        if ((!Char.IsNumber(c)) && (c != Convert.ToChar(Keys.Back)))
        {

        }
        else
        {
            append += c;
        }
    }

    ultraTextEditor1.Text = append;
}   
Dean Seo
  • 5,486
  • 3
  • 30
  • 49
Divya
  • 416
  • 5
  • 10
1

Here are more than 30 answers and a lot of answers are helpful. But I want to share a generalized form for the System.Windows.Forms.TextBox and System.Windows.Controls.TextBox.

There is not available KeyPress event in System.Windows.Controls.TextBox. This answer is for those people who want to implement with the same logic for System.Windows.Forms.TextBox and System.Windows.Controls.TextBox.

This is NumberTextBox code. Use commented line instead of the previous line for System.Windows.Controls.TextBox.

public class NumberTextBox : System.Windows.Forms.TextBox
//public class NumberTextBox : System.Windows.Controls.TextBox
{
    private double _maxValue;
    private double _minValue;
    private bool _flag;
    private string _previousValue;

    public NumberTextBox()
    {
        this.TextAlign = HorizontalAlignment.Right;
        //TextAlignment = TextAlignment.Right;
        KeyDown += TextBox_KeyDown;
        TextChanged += TextBox_TextChanged;
        _minValue = double.MinValue;
        _maxValue = double.MaxValue;
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        _previousValue = this.Text;
        _flag = this.SelectedText.Length > 0;
    }

    private void TextBox_TextChanged(object sender, EventArgs e)
    //private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        var text = this.Text;
        if (text.Length < 1) return;
        var cursorPosition = SelectionStart == 0 ? SelectionStart : SelectionStart - 1;
        var insertedChar = text[cursorPosition];
        if (IsInvalidInput(insertedChar, cursorPosition, text))
        {
            HandleText(text, cursorPosition);
        }
        ValidateRange(text, cursorPosition);
    }

    private bool IsInvalidInput(char insertedChar, int cursorPosition, string text)
    {
        return !char.IsDigit(insertedChar) && insertedChar != '.' && insertedChar != '-' ||
               insertedChar == '-' && cursorPosition != 0 ||
               text.Count(x => x == '.') > 1 ||
               text.Count(x => x == '-') > 1;
    }

    private void HandleText(string text, int cursorPosition)
    {
        this.Text = _flag ? _previousValue : text.Remove(cursorPosition, 1);
        this.SelectionStart = cursorPosition;
        this.SelectionLength = 0;
    }

    private void ValidateRange(string text, int cursorPosition)
    {
        try
        {
            if (text == "." || _minValue < 0 && text == "-") return;
            var doubleValue = Convert.ToDouble(text);
            if (doubleValue > _maxValue || doubleValue < _minValue)
            {
                HandleText(text, cursorPosition);
            }
        }
        catch (Exception)
        {
            HandleText(text, cursorPosition);
        }
    }

    protected void SetProperties(double minValue = double.MinValue, double maxValue = double.MaxValue)
    {
        _minValue = minValue;
        _maxValue = maxValue;
    }       

}

PositiveNumberTextBox code:

public class PositiveNumberTextBox : NumberTextBox
{
    public PositiveNumberTextBox()
    {
        SetProperties(0);
    }
}

FractionNumberTextBox code:

public class FractionNumberTextBox : NumberTextBox
{
    public FractionNumberTextBox()
    {
        SetProperties(0, 0.999999);
    }
}
osman
  • 43
  • 7
  • Can this work for a multiline textbox? I want to allow the user to enter positive doubles on multiple lines – Steve W Sep 16 '21 at 14:14
  • @SteveW, it doesn't work for multiline text. But you can Handle text after merging multiline values. – osman Sep 19 '21 at 09:21
1

one line code decimal point allowed

    private void txtQty_KeyPress(object sender, KeyPressEventArgs e)
    {
        e.Handled =  e.KeyChar != '.' && !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
    }
  • It's important to not just post code, but to also include a description of what the code does and why you are suggesting it. This helps others understand the context and purpose of the code, and makes it more useful for others who may be reading the question or answer. @John Garcia . – DSDmark Dec 23 '22 at 12:55
  • This won't work if a number is pasted into the textbox (from clipboard) – Umar T. Aug 16 '23 at 07:35
1

Sorry to wake the dead, but I thought someone might find this useful for future reference.

Here is how I handle it. It handles floating point numbers, but can easily be modified for integers.

Basically you can only press 0 - 9 and .

You can only have one 0 before the .

All other characters are ignored and the cursor position maintained.

    private bool _myTextBoxChanging = false;

    private void myTextBox_TextChanged(object sender, EventArgs e)
    {
        validateText(myTextBox);
    }

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        bool hasPeriod = false;
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            bool badChar = false;
            char s = text[i];
            if (s == '.')
            {
                if (hasPeriod)
                    badChar = true;
                else
                    hasPeriod = true;
            }
            else if (s < '0' || s > '9')
                badChar = true;

            if (!badChar)
                validText += s;
            else
            {
                if (i <= pos)
                    pos--;
            }
        }

        // trim starting 00s
        while (validText.Length >= 2 && validText[0] == '0')
        {
            if (validText[1] != '.')
            {
                validText = validText.Substring(1);
                if (pos < 2)
                    pos--;
            }
            else
                break;
        }

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

Here is a quickly modified int version:

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            char s = text[i];
            if (s < '0' || s > '9')
            {
                if (i <= pos)
                    pos--;
            }
            else
                validText += s;
        }

        // trim starting 00s 
        while (validText.Length >= 2 && validText.StartsWith("00")) 
        { 
            validText = validText.Substring(1); 
            if (pos < 2) 
                pos--; 
        } 

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }
yardape
  • 11
  • 2
0

3 solution

1)

//Add to the textbox's KeyPress event
//using Regex for number only textBox

private void txtBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), "\\d+"))
e.Handled = true;
}

2) an another solution from msdn

// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the     control.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
    // Determine whether the keystroke is a number from the keypad.
    if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
    {
        // Determine whether the keystroke is a backspace.
        if (e.KeyCode != Keys.Back)
        {
            // A non-numerical keystroke was pressed.
            // Set the flag to true and evaluate in KeyPress event.
            nonNumberEntered = true;
        }
    }
}

}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (nonNumberEntered == true)
    {
       MessageBox.Show("Please enter number only..."); 
       e.Handled = true;
    }
}

source http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(v=VS.90).aspx

3) using the MaskedTextBox: http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx

modest and cute girl
  • 785
  • 4
  • 13
  • 24
0

In button click you can check text of textbox by for loop:

char[] c = txtGetCustomerId.Text.ToCharArray();
bool IsDigi = true;

for (int i = 0; i < c.Length; i++)
     {
       if (c[i] < '0' || c[i] > '9')
      { IsDigi = false; }
     }
 if (IsDigi)
    { 
     // do something
    }
Shaahin
  • 1,195
  • 3
  • 14
  • 22
0

Simpler answer:

_textBox.TextChanged += delegate(System.Object o, System.EventArgs e)
{
    TextBox _tbox = o as TextBox;
    _tbox.Text = new string(_tbox.Text.Where(c => (char.IsDigit(c)) || (c == '.')).ToArray());
};
micahhoover
  • 2,101
  • 8
  • 33
  • 53
0

FAIL-SAFE and simple "recursive" method, which can be used with multiple textboxes.

It blocks the wrong keyboard typed characters and also pasted values etc. It only accepts integer numbers, and the maximum number length is the maximum length of a string type (which is int, really long!)

public void Check_If_Int_On_TextChanged(object sender, EventArgs e)
{
   // This method checks that each inputed character is a number. Any non-numeric
   // characters are removed from the text

   TextBox textbox = (TextBox)sender;

   // If the text is empty, return
   if (textbox.Text.Length == 0) { return; }

   // Check the new Text value if it's only numbers
   byte parsedValue;
   if (!byte.TryParse(textbox.Text[(textbox.Text.Length - 1)].ToString(), out parsedValue))
   {
      // Remove the last character as it wasn't a number
      textbox.Text = textbox.Text.Remove((textbox.Text.Length - 1));

      // Move the cursor to the end of text
      textbox.SelectionStart = textbox.Text.Length;
    }
 }
W0lfw00ds
  • 2,018
  • 14
  • 23
0

i like terse code

    private void xmm_textbox_KeyPress(object sender, KeyPressEventArgs e) {
        double x;
        e.Handled = !double.TryParse(((TextBox)sender).Text, out x);
    }
reza
  • 1,329
  • 2
  • 22
  • 37
0
Here is a simple solution that works for me.

public static bool numResult;
    public static bool checkTextisNumber(string numberVal)
    {
        try
        {
            if (numberVal.Equals("."))
            {
                numResult = true;
            }
            else if (numberVal.Equals(""))
            {
                numResult = true;
            }
            else
            {
                decimal number3 = 0;
                bool canConvert = decimal.TryParse(numberVal, out number3);
                if (canConvert == true)
                {
                    numResult = true;
                }
                else
                    numResult = false;
            }

        }
        catch (System.Exception ex)
        {
            numResult = false;
        }
        return numResult;
    }
    string correctNum;
    private void tBox_NumTester_TextChanged(object sender, TextChangedEventArgs e)
    {


        if(checkTextisNumber(tBox_NumTester.Text))
        {
            correctNum = tBox_NumTester.Text;
        }
        else
        {
            tBox_NumTester.Text = correctNum;
        }

    }
0

I had created a Re-Usable Textbox Extension class for all sorts of validations and thought about sharing it.

All you need to do is raise a TextChange event and then call the Validate method. It looks like this:

private void tbxAmount_TextChanged(object sender, EventArgs e)
{ 
    tbxAmount.Validate(TextValidator.ValidationType.Amount);
}

Here is the extension class:

public static class TextValidator
{
    public enum ValidationType
    {
        Amount,
        Integer
    }

    /// <summary>
    /// Validate a textbox on text change.
    /// </summary>
    /// <param name="tbx"></param>
    /// <param name="validationType"></param>
    public static void Validate(this TextBox tbx, ValidationType validationType)
    {
        PerformValidation(tbx, validationType);
        tbx.Select(tbx.Text.Length, 0);
    }


    private static void PerformValidation(this TextBox tbx, ValidationType validationType)
    {
        char[] enteredString = tbx.Text.ToCharArray();
        switch (validationType)
        {
            case ValidationType.Amount:
                tbx.Text = AmountValidation(enteredString);
                break;

            case ValidationType.Integer:
                tbx.Text = IntegerValidation(enteredString);
                break;

            default:
                break;
        }

        tbx.SelectionStart = tbx.Text.Length;
    }



    private static string AmountValidation(char[] enteredString)
    {
        string actualString = string.Empty;
        int count = 0;
        foreach (char c in enteredString.AsEnumerable())
        {
            if (count >= 1 && c == '.')
            { actualString.Replace(c, ' '); actualString.Trim(); }
            else
            {
                if (Char.IsDigit(c))
                {
                    actualString = actualString + c;
                }

                if (c == '.')
                {
                    actualString = actualString + c; count++;
                }

                else
                {
                    actualString.Replace(c, ' ');
                    actualString.Trim();
                }
            }
        }
        return actualString;
    }


    private static string IntegerValidation(char[] enteredString)
    {
        string actualString = string.Empty;
        foreach (char c in enteredString.AsEnumerable())
        {
            if (Char.IsDigit(c))
            {
                actualString = actualString + c;
            }
            else
            {
                actualString.Replace(c, ' ');
                actualString.Trim();
            }
        }
        return actualString;
    }
}

You can find the full code here

Ozesh
  • 6,536
  • 1
  • 25
  • 23
0

you can simply prevent adding non-numerical chars by this simple code

 if (long.TryParse(TextBox.Text,out long isparsable))
        {
          // your code to handle numbers
        }
        else
        {
            TextBox.Text="Only Numbers Allowed";
            TextBox.Focus();
            TextBox.SelectAll();
        }
Mohsen K
  • 257
  • 4
  • 10
0

Use a RegularExpressionValidator:

<asp:TextBox ID="TextBoxNum" runat="server"></asp:TextBox><br />
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
                        ControlToValidate="TextBoxNum" runat="server"
                        ErrorMessage="Only numbers allowed"
                        ValidationExpression="\d+">
</asp:RegularExpressionValidator>
Gerard Carbó
  • 1,775
  • 18
  • 16
0

The simplest and crudest way is to use a combobox instead of textbox with ReadOnly. But of course its only useful if you are expecting the user to use a decent and reasonable set of whole numbers, not try to touch infinity.

0
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);

if (!isNumber)
{ 
    (code if not an integer);
}
else
{
    (code if an integer);
}
T.Rob
  • 31,522
  • 9
  • 59
  • 103
newguy
  • 19
  • 1
-1

Working solution for WPF & a simple TextChangedEventArgs.

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    var TextBox = (sender as TextBox);

    // if not a numeric value, remove news characters
    if (Regex.IsMatch(TextBox.Text, "[^0-9]"))
    {
        foreach (TextChange Change in e.Changes)
        {
            TextBox.Text = TextBox.Text.Remove(Change.Offset, Change.AddedLength);

            TextBox.CaretIndex = Change.Offset;
        }
    }
}
Wang Liang
  • 4,244
  • 6
  • 22
  • 45
Lenor
  • 1,471
  • 10
  • 19
  • The question is about WinForms. There are no TextChangedEventArgs in WinForms' TextChanged event – elshev Mar 26 '20 at 04:13