Limit textbox.text to positiive and negative integers
-
IMO you can't check validity of user input by only watching which keys get presses; unless you are willing to not support pasting. A good user interface IMO will always support copy and paste, and the clipboard could contain arbitrary text. So you could: - save the content before the modification - read the content after modification - validate it (int.TryParse could be appropriate) - when not valid, restore the last saved content that was valid Warning: this gets tricky when intermediate values don't have a valid syntax, e.g. when you want to accept floating-point numbers in engineering format. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
Generally speaking, and in terms of best practices and such, you are of course entirely right. And I suppose I will be doing it your way in the end. But I don't have to like it ;P In this case I am handling a form with a bunch of textboxes, each representing a setting. Each setting is simply a value between -999 and 999, and won't be changed much. I suppose I am trusting the users to be lazy enough to not go through the trouble of copying and pasting such a short value. So I limited the max length to 3 (which brings to mind another problem), and I handle their KeyPress events to limit input to numbers. Anyway, now it is more a matter of interest than necessity. In other words can it be done?
My advice is free, and you may get what you paid for.
-
Generally speaking, and in terms of best practices and such, you are of course entirely right. And I suppose I will be doing it your way in the end. But I don't have to like it ;P In this case I am handling a form with a bunch of textboxes, each representing a setting. Each setting is simply a value between -999 and 999, and won't be changed much. I suppose I am trusting the users to be lazy enough to not go through the trouble of copying and pasting such a short value. So I limited the max length to 3 (which brings to mind another problem), and I handle their KeyPress events to limit input to numbers. Anyway, now it is more a matter of interest than necessity. In other words can it be done?
My advice is free, and you may get what you paid for.
of course it can be done. Assuming SelectionLength is zero, you would need TextBox.SelectionStart to know where the caret is, so you can perform the insert/append yourself, validate and then allow/disallow the keypress to be handled. And when SelectionLength isn't zero, the new character will replace all the ones selected; and you could handle that too. But is it all worth it? The popular approach is: - to only allow characters that could appear somewhere in the input - to validate afterwards So yes a minus sign is allowed, so KeyPressed accepts it; and no, it is not acceptable but as the first character, so int.TryParse() will make sure of that in the end. And then some people will advise to use a NumericUpDown thingy; I'm not one of them, as I find those controls horribly user-unfriendly. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
-
Generally speaking, and in terms of best practices and such, you are of course entirely right. And I suppose I will be doing it your way in the end. But I don't have to like it ;P In this case I am handling a form with a bunch of textboxes, each representing a setting. Each setting is simply a value between -999 and 999, and won't be changed much. I suppose I am trusting the users to be lazy enough to not go through the trouble of copying and pasting such a short value. So I limited the max length to 3 (which brings to mind another problem), and I handle their KeyPress events to limit input to numbers. Anyway, now it is more a matter of interest than necessity. In other words can it be done?
My advice is free, and you may get what you paid for.
-
Generally speaking, and in terms of best practices and such, you are of course entirely right. And I suppose I will be doing it your way in the end. But I don't have to like it ;P In this case I am handling a form with a bunch of textboxes, each representing a setting. Each setting is simply a value between -999 and 999, and won't be changed much. I suppose I am trusting the users to be lazy enough to not go through the trouble of copying and pasting such a short value. So I limited the max length to 3 (which brings to mind another problem), and I handle their KeyPress events to limit input to numbers. Anyway, now it is more a matter of interest than necessity. In other words can it be done?
My advice is free, and you may get what you paid for.
This thread must rate as one of the most asked questions on CodeProject, and Dave's[^] was the best answer. What is it that ties people to text boxes, when the
NumericUpDown
is designed out of the box to handle numbers only, and ranges for that matter? [Sorry: mini rant there, having seen the same question to many times] If the control you are using doesn't do the job, maybe you are using the wrong control.If you have knowledge, let others light their candles at it. Margaret Fuller (1810 - 1850) [My Articles] [My Website]
-
This thread must rate as one of the most asked questions on CodeProject, and Dave's[^] was the best answer. What is it that ties people to text boxes, when the
NumericUpDown
is designed out of the box to handle numbers only, and ranges for that matter? [Sorry: mini rant there, having seen the same question to many times] If the control you are using doesn't do the job, maybe you are using the wrong control.If you have knowledge, let others light their candles at it. Margaret Fuller (1810 - 1850) [My Articles] [My Website]
Don't worry, by all means, rant away. Just checked the numeric updown control, and although it does what Luc suggested, about going back to the last valid value, it doesn't do what I was after. In other words, indeed it efficiently corrects bad input, but it doesn't prevent it right from the bat, which was what I was interested in solving. I must admit I haven't really investigated the masked textbox though.
My advice is free, and you may get what you paid for.
-
Don't worry, by all means, rant away. Just checked the numeric updown control, and although it does what Luc suggested, about going back to the last valid value, it doesn't do what I was after. In other words, indeed it efficiently corrects bad input, but it doesn't prevent it right from the bat, which was what I was interested in solving. I must admit I haven't really investigated the masked textbox though.
My advice is free, and you may get what you paid for.
Don't know how your getting on, but i have just been playing this afternoon trying to write a function to see if it can be done This appears to work, and caters for various, minus and 0 entry perms. e.g. if you enter 0 then 1, the leading 0 is binned. e.g. if you enter 111 then a -, it will change it to -111 it won't allow 0000
Private Sub TextBox1\_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown Dim tb As TextBox = CType(sender, TextBox) Select Case e.KeyCode Case Keys.Decimal, Keys.OemPeriod If tb.Text.Contains(".") Then e.SuppressKeyPress = True Else If tb.TextLength = 0 Then tb.Text = "0" & tb.Text tb.SelectionStart = tb.TextLength ElseIf tb.TextLength = 1 And tb.Text.StartsWith("-") Then tb.Text = "-0" tb.SelectionStart = tb.TextLength End If End If Case Keys.Subtract, Keys.OemMinus 'Check the minus is not already present If tb.Text.Contains("-") Then e.SuppressKeyPress = True Else If tb.TextLength >= 1 Then 'PreFix the textbox with the minus tb.Text = "-" & tb.Text tb.SelectionStart = tb.TextLength e.SuppressKeyPress = True End If End If Case Keys.Back, Keys.Delete, Keys.Left, Keys.Right e.SuppressKeyPress = False Case Else 'Check for digits or discard If Not IsNumeric(Chr(e.KeyValue)) Then e.SuppressKeyPress = True Else 'Test for extra zero's e.g. 00001.234 If (e.KeyCode = Keys.D0 Or e.KeyCode = Keys.NumPad0) Then If tb.Text.Contains("0") And Not tb.Text.Contains(".") Then If Val(tb.Text) = 0 Then e.SuppressKeyPress = True End If Else If tb.Text.Contains(".") = False And tb.Text.Contains("0") Then If Val(tb.Text) = 0 Then tb.Text = tb.Text.Remove(tb.Text.Ind
-
Don't know how your getting on, but i have just been playing this afternoon trying to write a function to see if it can be done This appears to work, and caters for various, minus and 0 entry perms. e.g. if you enter 0 then 1, the leading 0 is binned. e.g. if you enter 111 then a -, it will change it to -111 it won't allow 0000
Private Sub TextBox1\_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown Dim tb As TextBox = CType(sender, TextBox) Select Case e.KeyCode Case Keys.Decimal, Keys.OemPeriod If tb.Text.Contains(".") Then e.SuppressKeyPress = True Else If tb.TextLength = 0 Then tb.Text = "0" & tb.Text tb.SelectionStart = tb.TextLength ElseIf tb.TextLength = 1 And tb.Text.StartsWith("-") Then tb.Text = "-0" tb.SelectionStart = tb.TextLength End If End If Case Keys.Subtract, Keys.OemMinus 'Check the minus is not already present If tb.Text.Contains("-") Then e.SuppressKeyPress = True Else If tb.TextLength >= 1 Then 'PreFix the textbox with the minus tb.Text = "-" & tb.Text tb.SelectionStart = tb.TextLength e.SuppressKeyPress = True End If End If Case Keys.Back, Keys.Delete, Keys.Left, Keys.Right e.SuppressKeyPress = False Case Else 'Check for digits or discard If Not IsNumeric(Chr(e.KeyValue)) Then e.SuppressKeyPress = True Else 'Test for extra zero's e.g. 00001.234 If (e.KeyCode = Keys.D0 Or e.KeyCode = Keys.NumPad0) Then If tb.Text.Contains("0") And Not tb.Text.Contains(".") Then If Val(tb.Text) = 0 Then e.SuppressKeyPress = True End If Else If tb.Text.Contains(".") = False And tb.Text.Contains("0") Then If Val(tb.Text) = 0 Then tb.Text = tb.Text.Remove(tb.Text.Ind
That is a lot of code for a very subjective set of validity rules. I think you are ignoring the current selection; if anything is selected, typing would replace it. And I still want to paste something into the control! So I'd go for a second, hidden control in the KeyDown handler, which deals with the editing, then apply whatever rules (or TryParse) to the content (not the latest change) to determine validity. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
-
That is a lot of code for a very subjective set of validity rules. I think you are ignoring the current selection; if anything is selected, typing would replace it. And I still want to paste something into the control! So I'd go for a second, hidden control in the KeyDown handler, which deals with the editing, then apply whatever rules (or TryParse) to the content (not the latest change) to determine validity. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
i know, i know, i was just playing though! It maybe doesn't meet your needs, but it might (unlikely) fit Johans, failing that it may give him ideas of how to come up with his own validation requirements to meet his own needs. i'm going for chocolate, irn-bru and a ciggy now. :)
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com -
i know, i know, i was just playing though! It maybe doesn't meet your needs, but it might (unlikely) fit Johans, failing that it may give him ideas of how to come up with his own validation requirements to meet his own needs. i'm going for chocolate, irn-bru and a ciggy now. :)
Dave Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.comEnjoy. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
-
Don't know how your getting on, but i have just been playing this afternoon trying to write a function to see if it can be done This appears to work, and caters for various, minus and 0 entry perms. e.g. if you enter 0 then 1, the leading 0 is binned. e.g. if you enter 111 then a -, it will change it to -111 it won't allow 0000
Private Sub TextBox1\_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown Dim tb As TextBox = CType(sender, TextBox) Select Case e.KeyCode Case Keys.Decimal, Keys.OemPeriod If tb.Text.Contains(".") Then e.SuppressKeyPress = True Else If tb.TextLength = 0 Then tb.Text = "0" & tb.Text tb.SelectionStart = tb.TextLength ElseIf tb.TextLength = 1 And tb.Text.StartsWith("-") Then tb.Text = "-0" tb.SelectionStart = tb.TextLength End If End If Case Keys.Subtract, Keys.OemMinus 'Check the minus is not already present If tb.Text.Contains("-") Then e.SuppressKeyPress = True Else If tb.TextLength >= 1 Then 'PreFix the textbox with the minus tb.Text = "-" & tb.Text tb.SelectionStart = tb.TextLength e.SuppressKeyPress = True End If End If Case Keys.Back, Keys.Delete, Keys.Left, Keys.Right e.SuppressKeyPress = False Case Else 'Check for digits or discard If Not IsNumeric(Chr(e.KeyValue)) Then e.SuppressKeyPress = True Else 'Test for extra zero's e.g. 00001.234 If (e.KeyCode = Keys.D0 Or e.KeyCode = Keys.NumPad0) Then If tb.Text.Contains("0") And Not tb.Text.Contains(".") Then If Val(tb.Text) = 0 Then e.SuppressKeyPress = True End If Else If tb.Text.Contains(".") = False And tb.Text.Contains("0") Then If Val(tb.Text) = 0 Then tb.Text = tb.Text.Remove(tb.Text.Ind
Very nice indeed. I hadn't considered the multiple zero, and leading zero scenarios yet, good catch. Now I haven't bothered (yet) checking for decimal separators, as I was looking to limit to whole integers, so using Luc's advice, I got this: In a generic KeyPress event that handles all textboxes:
Select Case True
Case e.KeyChar = CChar("-")
If sender.SelectionStart > 0 Or sender.Text.Contains("-") Then
e.Handled = True
End If
Case Not Char.IsDigit(e.KeyChar)
e.Handled = True
End Select...and in a generic Leave event that handles all textboxes:
If sender.text.length < 1 Or sender.text = "0" Or sender.text = "-" Then
MsgBox("The field may not be empty, and the value may not be zero or just minus.", MsgBoxStyle.Critical)
sender.text = "1"
sender.focus()
End IfNow that you made me aware of it, I think I'll just use the Leave event to drop leading zeros and check for multiple-zeros-only.
My advice is free, and you may get what you paid for.