How to validate textbox array elements created through loop using VB.net? - vb.net

I have created 288 textboxes through array and loop in VB.net. Is there any possible way on validating each textbox on KeyPress event to determine if the input is an integer? Thanks so much for your help!

You can do this by adding event handler in the array function.
Dim txt As TextBox
AddHandler txt.KeyPress, AddressOf KeyPressToCheckInput
then write the KeyPress Function
Sub KeyPressToCheckInput(sender As Object, e As KeyPressEventArgs)
If e.KeyChar <> ChrW(Keys.Back) Then 'checks for backspace
If Char.IsNumber(e.KeyChar) Then
'anything you want to do about it'
Else
e.Handled = True 'ignores if the character is not a number
End If
End If
End Sub

Related

KeyPress handler being applied to wrong control

I have a .KeyPress event handler which is supposed to limit/control the keys which can be entered in a specific TextBox (more precisely, any of the textboxes in a specific DataGridViewTextBoxColumn)
Private Sub dgv_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles dgv.EditingControlShowing
If dgv.CurrentCell.ColumnIndex = myColumn.Index And Not e.Control Is Nothing Then
DirectCast(e.Control, TextBox).CharacterCasing = CharacterCasing.Upper
DirectCast(e.Control, TextBox).MaxLength = 10
AddHandler DirectCast(e.Control, TextBox).KeyPress, AddressOf controlKeyPress
End If
End Sub
Private Sub controlKeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
Dim charEnum As Integer = CUInt(Microsoft.VisualBasic.Asc(e.KeyChar))
Dim tb As TextBox = DirectCast(sender, TextBox)
Select Case charEnum
Case 8
' Always permit the keying of backspace (no suppression)
Case 42
' Permit the keying of asterisk (42) but only if it is the first character (otherwise, suppress the key press)
If Not tb.SelectionStart = 0 Then e.KeyChar = ""
Case 46
' Permit the keying of period (46) but only if it is not the first character and the first character is not an asterisk (otherwise, suppress the key press)
If tb.SelectionStart = 0 OrElse tb.Text.FirstOrDefault = "*" Then e.KeyChar = ""
Case 65 To 90, 97 To 122
' Permit the keying of upper-case alpha (65-90) and lower-case alpha (97-122) as long as the first character is not an asterisk (otherwise, suppress the key press)
If tb.Text.FirstOrDefault = "*" Then e.KeyChar = ""
Case Else
' All other characters, suppress the key press (set the KeyChar to nothing)
e.KeyChar = ""
End Select
End Sub
What's weird is, the same handler seems to be getting applied to other TextBox controls in the DataGridView, but in a different column (i.e. not in myColumn) Which is strange because I have a specific condition in the EditingControlShowing event that specifies that the handler should only be applied if the .ColumnIndex of the control matches that of the column to which it should apply (i.e. If dgv.CurrentCell.ColumnIndex = myColumn.Index) So I'm not sure why the same handler is being applied to a TextBox that's not in myColumn?
Also, it doesn't appear to be consistent - when I initially load the DGV, the other textboxes have no restrictions on them (as expected); when I go to edit a row, and the handler is applied to myColumn (as expected), the same handler also seems to be applied immediately to any other textboxes in the same row (but in debugging, I can't seem to trap where this happens, I can only trap the application of the event handler to the correct control)
I'm not sure if I should have a RemoveHandler call somewhere - and if so, where, because I can't find the point at which the handler is being applied erroneously in the first place?
I tried this but it doesn't seem to have any effect (again, while debugging, when I click in a TextBox in myOtherColumn, it does hit that line, but the restriction is still imposed anyway?)
Private Sub dgv_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles dgv.EditingControlShowing
If dgv.CurrentCell.ColumnIndex = myColumn.Index Then
DirectCast(e.Control, TextBox).CharacterCasing = CharacterCasing.Upper
DirectCast(e.Control, TextBox).MaxLength = 10
AddHandler DirectCast(e.Control, TextBox).KeyPress, AddressOf controlKeyPress
ElseIf dgv.CurrentCell.ColumnIndex = myOtherColumn.Index Then
RemoveHandler DirectCast(e.Control, TextBox).KeyPress, AddressOf controlKeyPress
End If
End Sub
All suggestions welcome!
The DataGridView control will reuse an editing control if it can to improve performance. You should keep a reference to the editing control from the EditingControlShowing event handler and use a RemoveHandler statement in the CellEndEdit event handler.
Actually, you may not need to keep the reference. You may be able to use the EditingControl property of the grid. Try that first.
EDIT:
I have just tested for myself and the EditingControl property of the grid is Nothing when the CellEndEdit event is raised, so my second suggestion above is out. That means that you need to retain a reference to the editing control from the EditingControlShowing event handler. If you're going to do that though, you may as well not use AddHandler and RemoveHandler. It's simpler to declare the field WithEvents and then use a Handles clause on the event handler, e.g.
Private WithEvents editingControl As TextBox
Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
If DataGridView1.CurrentCell.ColumnIndex = 0 Then
editingControl = DirectCast(e.Control, TextBox)
End If
End Sub
Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
editingControl = Nothing
End Sub
Private Sub EditingControl_KeyPress(sender As Object, e As KeyPressEventArgs) Handles editingControl.KeyPress
Console.WriteLine(e.KeyChar)
End Sub
That code will assign the editing control to the field if and only if the cell being edited is in the first column. Any control assigned to that field will have its events handled and the field is always reset when an editing session ends.

Data Type validation in textbox

Trying to make a validation where only letters can be entered into a textbox. I've got that part working, but I would also like the ability for the user to use the backspace button, and I'm not sure how
Private Sub TxtBoxCustForename_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TxtBoxCustForename.KeyPress
If Asc(e.KeyChar) < 65 Or Asc(e.KeyChar) > 122 Then 'Ensures only letters can be entered by using the ASCII converter'
e.Handled = True
MessageBox.Show("You may only input letters")
End If
End Sub
Input validation is a built-in feature of .NET. You don't need to capture key presses and manually code your own solution.
You might want to use a MaskedTextBox as suggested in this article:
https://learn.microsoft.com/en-us/dotnet/framework/winforms/user-input-validation-in-windows-forms
You can change your If statement like this:
If (Asc(e.KeyChar) < 65 Or Asc(e.KeyChar) > 122) And Asc(e.KeyChar) <> 8 Then
Ascii 8 is the Backspace key.
Rather than using the KeyPress event, use the TextChanged event. Also, I would recommend using the IsNumeric function to test whether it is a number or not.
Private Sub TxtBoxCustForename_KeyPress(sender As Object, e As EventArgs) Handles TxtBoxCustForename.TextChanged
For Each entry as Char in TxtBoxCustForename.Text
If IsNumeric(entry) Then
MessageBox.Show("You may only input letters")
Exit For
End If
Next
End Sub
If you're going to use .NET then use .NET.
Private Sub TxtBoxCustForename_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TxtBoxCustForename.KeyPress
Dim keyChar = e.KeyChar
If Not Char.IsLetter(keyChar) AndAlso Not Char.IsControl(keyChar) Then
e.Handled = True
MessageBox.Show("You may only input letters")
End If
End Sub
This still doesn;t prevent the user pasting invalid text into the control though, so you still need to handle the Validating event or use a custom control that catches paste operations.

How can I make it so a TextBox will dynamically adjust the input as a currency format?

This app I'm designing has a TextBox named txtValue with the properties MaxLength set to 14 and TextAlign set to Right. I want txtValue to only accept currency, and dynamically format the input so the user doesn't need to add commas, only one period.
I managed to make it so txtValue will only accept numbers and one dot in the event txtValue_KeyPress.
txtValue_LostFocus will convert the input into currency format.
Here's my code so far:
Private Sub txtValue_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtValue.KeyPress
'Allows only one dot
If (e.KeyChar.ToString = ".") And (txtValue.Text.Contains(e.KeyChar.ToString)) Then
e.Handled = True
Exit Sub
End If
'Allows only 0 to 9 and dot (once)
If (e.KeyChar.ToString < "0" OrElse e.KeyChar.ToString > "9") _
AndAlso e.KeyChar <> ControlChars.Back _
AndAlso e.KeyChar.ToString <> "." Then
e.Handled = True
End If
End Sub
Private Sub txtValue_LostFocus(sender As Object, e As EventArgs) Handles txtValue.LostFocus
txtValue.Text = Format(Val(txtValue.Text), "000,000,000.00")
End Sub
I expect the input -q1w23456789012....34 to return the output 123,456,789,012.34, but the actual output after it loses focus is 123,456,789,012.30
This seems like an easy fix, like setting MaxLength to 15, but then if I don't type a period, it'll allow me to type 15 numbers and I only want up to 12 plus 2 after the period.
I expect the input -q1w234....5678 to return the output 1,234.56, but the actual output after it loses focus is 000,000,001,234.56
This seems like a more complex fix, because I don't want to use the LostFocus event to validate what I type. I want the KeyPress event to handle the input and dynamically format what I type.
In this case:
The input 1 would have the output 1.00
The input 123.4 would have the output 123.40
The input 1234.567 would have the output 1,234.56
All of this without needing the LostFocus event, but right now I'm using the LostFocus event because that's all my very limited knowledge allows me to do.
UPDATE
Alright I'm now using the Leave event, but then again I was only using LostFocus as a placeholder because in the end I want the TextBox to adjust what the user types as they type.
An alternative way to handle. For details on formating numbers for display try MS docs https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings or https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings
Private err As New ErrorProvider()
Private d As Decimal 'In case you want to use the value as a number somewhere else
Private Sub TextBox17_Validating(sender As Object, e As CancelEventArgs) Handles TextBox17.Validating
If Not Decimal.TryParse(TextBox17.Text, d) Then
e.Cancel = True
err.SetError(TextBox17, "This text box must contain a number.")
Else
err.Clear()
End If
End Sub
Private Sub TextBox17_Validated(sender As Object, e As EventArgs) Handles TextBox17.Validated
TextBox17.Text = d.ToString("C")
End Sub

VB.NET 2010 DataGridView Handling Keypress via EditingControlShowing Event

I am working with a DataGridView for the first time and while I have MANY questions, this latest issue is vexing me.
Summary of issue:
I have a DataGridView (dgv) which I have a set of columns defined. Some readonly some editable.
For the editable columns I need four things to occur.
1) Allow Numeric entry
2) Allow maximum of 2 digits
3) Zero Pad any entries <2 digits
4) My ISSUE:
If the user types in a two digit number, I want to detect that and TAB to the next column. I cannot get this to work.
Sample code (with some known working items left out):
Private Sub dgvDiary_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvDiary.EditingControlShowing
Dim txtEdit As TextBox = e.Control
txtEdit.MaxLength = 2
'remove any existing handler
RemoveHandler txtEdit.KeyPress, AddressOf txtdgvDiaryEdit_Keypress
AddHandler txtEdit.KeyPress, AddressOf txtdgvDiaryEdit_Keypress
End Sub
Private Sub txtdgvDiaryEdit_Keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
'Test for numeric value or backspace
If IsNumeric(e.KeyChar.ToString()) _
Or e.KeyChar = ChrW(Keys.Back) Then
e.Handled = False 'if numeric
Else
e.Handled = True 'if non numeric
End If
'If user typed in 2 characters, move on!
'Don't work!
If Strings.Len(Me.dgvDiary.Rows(Me.dgvDiary.CurrentRow.Index).Cells(Me.dgvDiary.CurrentCell.ColumnIndex).Value) = 2 Then
SendKeys.Send("{TAB}")
End If
End Sub
Basically during this event I'm not able to see what the value of the cell "will be" when entered.
I tried adding a ".RefreshEdit" and a ".Commit" but they didn't work.
Any way to test the code within this event OR is there an event that would fire IMMEDIATELY afterward that I can use?
You are looking in the wrong place. You need to examine the text in the TextBox, not the grid, to see how many characters are currently being typed. Try using the TextChanged event for that:
Private Sub txtdgvDiaryEdit_TextChanged(sender As Object, e As EventArgs)
If DirectCast(sender, TextBox).Text.Length = 2 Then
SendKeys.Send("{TAB}")
End If
End Sub
Like your other code, add the handlers:
'remove any existing handler
RemoveHandler txtEdit.TextChanged, AddressOf txtdgvDiaryEdit_TextChanged
AddHandler txtEdit.TextChanged, AddressOf txtdgvDiaryEdit_TextChanged
RemoveHandler txtEdit.KeyPress, AddressOf txtdgvDiaryEdit_KeyPress
AddHandler txtEdit.KeyPress, AddressOf txtdgvDiaryEdit_KeyPress
Alternatively, you can check to see if the TextBox only has one character, and if the KeyPress is passing in another number, send your Tab key then. You would remove the TextChanged event code in this case:
Private Sub txtdgvDiaryEdit_KeyPress(sender As Object, e As KeyPressEventArgs)
'Test for numeric value or backspace
If IsNumeric(e.KeyChar.ToString()) _
Or e.KeyChar = ChrW(Keys.Back) Then
e.Handled = False 'if numeric
Else
e.Handled = True 'if non numeric
End If
If DirectCast(sender, TextBox).Text.Length = 1 AndAlso Char.IsNumber(e.KeyChar) Then
SendKeys.Send("{TAB}")
End If
End Sub

How to prevent special characters in datagridview using vb.net

I have a windows forms vb.net program that uses a datagridview. I'm trying to find a way to prevent a user from entering special characters (e.g. $,#,!,#,%,^,&) in my datagridview. When the user inputs a special character I have an approprioate message box appear explaining their mistake, then I provide them a default value. I have everything working except a way to prevent the special character or symbols. I'm thinking something like this has to work, but I can't seem to find any way of preventing this sort of entry:
If (columnindex = 0) Then 'checking value for column 1 only
Dim cellString = DataGridView1.Rows(rowindex).Cells(columnindex).value
If cellString String.IsSymbol(cellString) = true Then
MessageBox.Show("Special Characters Not Allowed")
End If
DataGridView1.Rows(rowindex).Cells(columnindex).value = "Default Value"
Exit Sub
End If
You can use the EditingControlShowing event to register a KeyPress function for the input box.
Private Sub YourDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles YourDataGridView.EditingControlShowing
Try
RemoveHandler e.Control.KeyPress, AddressOf YourFunctionToPreventSpecialCharacters
Catch ex As Exception
End Try
If Me.dgvTableViewer.CurrentCell.ColumnIndex = YourDataGridView.Columns("YourColumn").Index Then
AddHandler e.Control.KeyPress, AddressOf YourFunctionToPreventSpecialCharacters
End If
End Sub
Try and Put this in the DataGridView's keydown event:
Private Sub DataGridView1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown
Select Case e.KeyCode
Case Keys.D0 To Keys.D9 And e.Shift
MsgBox("NOPE.")
e.SuppressKeyPress = True
End Select
End Sub
That basically checks if the keypress is coming from the 0-9 keys on your computer and also if you are holding the SHIFT Key. If it is then it displays a Msgbox and Suppresses the keypress. This blocks chars on your keyboard's 0-9 shift !##$%^&*(). You can edit this like
Case Keys.A
e.Suppress ...
Msgbox ... etc