2

Recently I've notice, some smart user pass string (alphabets) in the TextBox that allow only number value (0-9) during KeyPress Event in one my projects. Unfortunately the database column type in NVARCHAR, that's why data inserting operation is completing with with invalid data. My project (Winform) is big enough to change data type of that column (NVARCHAR to INT). I got error while calculating SUM of that column in SQL Server. Here is my KeyPress Event for number only validation.

private void txtInputValue_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!char.IsDigit(e.KeyChar)) e.Handled = true;         //Just Digits
    if (e.KeyChar == (char)8) e.Handled = false;            //Allow Backspace
}

Now how can I prevent user to stop paste some invalid data except Number (0-9). Thanks in advance for help me.

Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
Jakir Hossain
  • 421
  • 1
  • 7
  • 16
  • 2
    [`TextBox.ShortcutsEnabled = false`](http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.shortcutsenabled%28v=vs.110%29.aspx) ? – Sriram Sakthivel Dec 11 '14 at 12:57
  • Is your project WinForms, WPF or something else? – Andrey Korneyev Dec 11 '14 at 12:58
  • It's likely WinForms since the event handler is giving a `KeyPressEventArgs`. – vcsjones Dec 11 '14 at 12:59
  • 2
    I'd suggest not checking inputs on every keypress event, but rather wait for the textchanged event and then check whether it is valid input to you (i.e. numeric or what have you), that way you also dont rob the user of well known practices such as copypasting. – DrCopyPaste Dec 11 '14 at 13:00
  • Another approach (not as good as `MaskedTextBox`, but still user friendly) is to let user type in anything (it should be clear what input is expected though), but validate *value* as it's changed (in `TextChanged` event handler). Validation result can be displayed to user, so that he can correct his mistake, without restricting his input. Good example is entering `double` values. If `double.TryParse` fails, then you can display red border or some icon to inform user what input is wrong. This approach is very good to handle special cases (blank values, constants: `NaN`, `+Infinity`, etc.). – Sinatr Dec 11 '14 at 13:34

3 Answers3

3

Assuming your project is WinForms - you are heading the wrong way.

It looks like all you need - is MaskedTextBox.

In that control you can set the Mask property for "digits only" mask preventing input of "non-digit" characters not only from keyboard, but also from pasting.

See MSDN for reference about mask format.

Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
3

You can simply set the ShortcutsEnabled of your textbox to false. (As suggested by Sriram Sakthivel)

txtInputValue.ShortcutsEnabled = false;
Community
  • 1
  • 1
Ludovic Feltz
  • 11,416
  • 4
  • 47
  • 63
0

With KeyPress add TextChanged event also as like,

    private void txtInputValue_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsDigit(e.KeyChar)) e.Handled = true;         //Just Digits
        if (e.KeyChar == (char)8) e.Handled = false;            //Allow Backspace
    }

    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 = string.Empty;
        }
    }

Hope this helps...

Vanest
  • 906
  • 5
  • 14
  • 3
    This suggestion is a usability horror: don't use MessageBox and certainly don't clear the entire textbox when one wrong character has been entered. – CodeCaster Dec 11 '14 at 13:02
  • @CodeCaster Wrong character will be prevented by KeyPress event and this will pop-up only for pasted text... – Vanest Dec 11 '14 at 13:05
  • And now it doesn't allow using the arrow keys, and still clears the entire textbox when the user manages to get one non-numeric character in there. Do not reinvent the wheel poorly. Use a masked textbox or tested code. – CodeCaster Dec 11 '14 at 13:10
  • @CodeCaster I accept masked textbox is the solution, but the combination of KeyPress and TextChanged events works for me, I have tested it with my knowledge. Only when there is a paste of alphabets from mouse pointer, it clears the text. – Vanest Dec 11 '14 at 13:55
  • @CodeCaster Sometimes reinventions give better options... – Vanest Dec 11 '14 at 14:03
  • Alright, let me rephrase. Apart from selecting `Paste` from the context menu, one can also paste using `Ctrl+V` and `Shift+Insert`. Users expect this behavior, so you should not limit it. Your `KeyPress` handler prevents `Ctrl+V`, usability issue 1. When a textbox allows only numbers, users still expect to be able to paste numbers from the clipboard. This works (using context menu or `Shift+Insert`) - unless the text-to-paste contains non-numeric information, such as whitespace, which is common for copied text. Code should silently swallow this whitespace, and only enter the numbers. – CodeCaster Dec 11 '14 at 14:19
  • Lastly, when the user has entered data and accidentally pastes invalid data, you clear the **entire** textbox - which is frustrating. That is why reinventing the wheel poorly is a usability issue and not very useful. There are already loads and loads of equivalent code on this site, all with the same kinds of issues, and we should not promote code like this. Finally I was confusing `KeyPress` with `KeyDown`, where the latter _does_ fire for arrow keys: users expect to be able to select text using `Shift+Arrow` - at least this code still allows that. – CodeCaster Dec 11 '14 at 14:21