Validating textbox when enter button is pushed - vb.net

I'm creating a AddIn for Autodesk Inventor (3D drawing software), and for the moment I am playing with positional constraints.
I created a custom user menu for quick editing certain values, in this case the elevation and orientation value.
First I used the textbox.textchanged event to change my constraint value. But this was working not 100%. Example when pressing elevation 1000 would change the elevation 4 times ( on per digit ).
Now I went to using the validated event. This works better, BUT I would like to have the textbox to initiate validation when the Enter button is pressed. For this I whipped up this, but it's not correct i'm sure of it. How should I write this correctly?
The code below works but, I would like to have a proper way to achieve the result.
Private Sub tbElevationValue_TextChanged(sender As Object, e As EventArgs) _
Handles tbElevation.Validated
' If the elevation parameter and textbox value are the same
' The sub must be aborted
If CDbl(tbElevation.Text) = oElevationParameter.Value * 10 Then Exit Sub
' Check the entered value
Dim oValue As Double
If tbElevation.Text = "" Then
oValue = 0
tbElevation.Text = 0
Else
oValue = tbElevation.Text
End If
' Set the parameter value
oElevationParameter.Value = oValue / 10
' Update the document
EM_AddIn.StandardAddInServer.m_inventorApplication.ActiveDocument.Update()
End Sub
Private Sub tbOrientation_TextChanged(sender As Object, e As EventArgs) _
Handles tbOrientation.Validated
' If the orientation parameter and textbox value are the same
' The sub must be aborted
If CDbl(tbOrientation.Text) = cRandiansToDegrees(oOrientationParameter.Value) Then Exit Sub
' Check the entered value
Dim oValue As Double
If tbOrientation.Text = "" Then
oValue = 0
tbOrientation.Text = 0
Else
oValue = tbOrientation.Text
End If
' Set the parameter value
oOrientationParameter.Value = cDegreesToRandians(oValue)
' Update the document
EM_AddIn.StandardAddInServer.m_inventorApplication.ActiveDocument.Update()
End Sub
Private Sub OrientationElevationEnterKey_Pressed(sender As Object, e As Windows.Forms.KeyEventArgs) Handles tbElevation.KeyUp, tbOrientation.KeyUp
If e.KeyCode = Windows.Forms.Keys.Enter Then
CType(sender, Windows.Forms.TextBox).Parent.Focus()
CType(sender, Windows.Forms.TextBox).Focus()
End If
End Sub

I think you're on the right way. It can be a pain to register a key_down event for each TextBox object, but your idea is good.
You can set a key_down event listener to your form instead.
Try something like this:
Private Sub Main_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.KeyCode = Keys.KeyCode.Enter Then
MyBase.Focus() ' this will cause the currently focused control to validate
End If
End Sub

Related

Implementing a Text change event from an Array

I am looking to change textbox fore and back colors of multiple textboxes based on a value if any one of the textboxes change it's value either by user input or reading from the DB.
I am not sure how to implement the code once an individual textbox has a change. The below code is as far as I got as I do not know how to implement it to work. Can someone assist?
Private Sub DiffCalcColor_TextChanged(sender As Object, e As EventArgs) Handles tbPMDiffCalc.TextChanged, tbLHDiffCalc.TextChanged, tbRFDiffCalc.TextChanged, tbFSDiffCalc.TextChanged, tbFSADiffCalc.TextChanged
Dim tb = DirectCast(sender, TextBox)
Dim text = tb.Text.Replace("$", "")
Dim number As Decimal
Decimal.TryParse(text, number)
Select Case number
Case < 0D : tb.ForeColor = Color.DarkRed
tb.BackColor = Color.White
Case > 0D : tb.ForeColor = Color.Green
tb.BackColor = Color.White
Case = 0D : tb.ForeColor = Color.DimGray
tb.BackColor = Color.Gainsboro
Case Else
Exit Select
End Select
End Sub
If you want to handle the same event for multiple controls with a single method then you simply include all those controls in the Handles clause, e.g.
Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged,
TextBox2.TextChanged
Dim eventRaiser = DirectCast(sender, TextBox)
'Get the text that just changed.
Dim text = eventRaiser.Text
Dim number As Decimal
'Try to convert it to a number.
Decimal.TryParse(text, number)
'Use the number to decide how to format.
If number = Decimal.Zero Then
'...
Else
'...
End If
End Sub
You can do that manually or you can let the designer do it for you. To do the latter, start by selecting the multiple controls in the designer, then open the Properties window, click the Events button on the toolbar, then double-click the appropriate event. That will generate an event handler, much like double-clicking on a single control does, but it will add all the selected controls to the Handles clause. It also allows you to generate a handler for any event, rather than just the default event. To add a control to that Handles clause, you can select one or more controls, select the event and then select an existing event handler from the drop-down.

Avoid some functions/events to run when one function/events is clicked or executed

im developing a system using vb.net and i have some question about datagridview function. Is it possible in gridview that when i click the rowheader function it will not execute the cell enter function of it?
Because my problem is in my cell enter event/function there is a code that will show some text box if the user enter on the 1st cell. and i want that when i click the row header of my grid view this cell enter event/function will not be executed. is it possible guys? give me some tips or tricks on how to do it.
i've also done trying like this
Private sub gridview_RowHeaderMouseClick . . .
textbox.visible = false
gridview.endEdit(true)
end sub
the result is okay but it is not good for the client view and i want to improve it more.
This is my code.
Private Sub dgCharges_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgCharges.CellEnter
if e.ColumnIdex >= 0 Then
if e.ColumnIndex = 5 Then
'Show Textbox.
End If
End if
End Sub
Private Sub dgCharges_RowHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles dgCharges.RowHeaderMouseClick
'Textbox.visible = false //this line i've use to hide the textbox when user
clicked row header.
dgCharges.EndEdit(True)
End Sub
Just put a test in the CellEnter function that only executes the restricted part of the code if the column index >= 0. The header has index -1
Private Sub DataGridView1_CellEnter(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
If e.ColumnIndex >= 0 Then
'Do my stuff
End If
End Sub
------ EDIT ----
To prevent the datagridview cell editors from popping up just set the column to readonly. Alternatively for more control use
Private Sub DataGridView1_CellBeginEdit(sender As System.Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridViewMsg.CellBeginEdit
'Test your criteria
If shouldBeReadonly Then
e.Cancel = True
End If
End Sub

changing calculate button to restart button after clicked

Is there any way to change a button to another button while running the program, i.e when the user clicks a button called "display", it calculates the results, then "display" turns into "Restart?" and if the user clicks that it restarts the program? I would like to change btnDisplay to btnRestart:
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
' displays a student's grade
Double.TryParse(txtEarned.Text, dblEarned)
For Each minimum As Double In dblMinimumPoints
If dblEarned >= minimum Then
lblGrade.Text = strGrade(gradeIndex)
gradeIndex += 1
End If
Next
txtEarned.ReadOnly = False
btnDisplay.Enabled = False
End Sub
I suppose there are multiple ways to do this. One is to have two buttons, btnDisplay and btnRestart, each with desired Text, that are laid on top of each other in the form designer. Alternate which one is visible when they are clicked.
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
' displays a student's grade
Double.TryParse(txtEarned.Text, dblEarned)
For Each minimum As Double In dblMinimumPoints
If dblEarned >= minimum Then
lblGrade.Text = strGrade(gradeIndex)
gradeIndex += 1
End If
Next
txtEarned.ReadOnly = False
btnDisplay.Visible = False
btnReset.Visible = True
End Sub
I'm not sure what you mean by saying that btnRestart will "restart the program", but presumably in its click event you would likewise hide it and make btnDisplay visible again.
(Also you might want to add some Try...Finally error handling in these events, so that even if something goes wrong, you can be sure the Visible lines will be executed.)
In your handler onclick and add a select case based on the .text attribute, then if the text is display update it it to restart, if it is restart then add a goto to where you want the script to start from on restart.
EDIT, below I have added the codetorun as a function which is probably a better solution than goto:
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
Select Case btnDisplay.Text
Case "Submit"
codeiwanttorun()
btnDisplay.Text = "Restart"
Case "Restart"
codeiwanttorun()
End Select
End Sub
Private Function codeiwanttorun()
Double.TryParse(txtEarned.Text, dblEarned)
For Each minimum As Double In dblMinimumPoints
If dblEarned >= minimum Then
lblGrade.Text = strGrade(gradeIndex)
gradeIndex += 1
End If
Next
End Function

Checkbox returned in Event Handler isn't one on form

I'm creating an array of checkboxes on a form dynamically; the code that creates the array looks like this:-
checkbox_array(count_of_checkboxes) = New CheckBox
if (count_of_checkboxes = 0) Then
checkbox_array(count_of_checkboxes).Top = specimen_checkbox.Top
checkbox_array(count_of_checkboxes).Left = specimen_checkbox.Left
else
checkbox_array(count_of_checkboxes).Top = checkbox_array(count_of_checkboxes - 1).Top + vertical_offset
checkbox_array(count_of_checkboxes).Left = checkbox_array(count_of_checkboxes - 1).Left + horizontal_offset
End If
my_panel.Controls.Add(checkbox_array(count_of_checkboxes))
AddHandler checkbox_array(count_of_checkboxes).MouseClick, cbxSpecimen_CheckedChanged
checkbox_array(count_of_checkboxes).Name = someValue
checkbox_array(count_of_checkboxes).Text = someValue
checkbox_array(count_of_checkboxes).Enabled = true
checkbox_array(count_of_checkboxes).Visible = true
checkbox_array(count_of_checkboxes).Show()
This works fine and dandy on one form. However, I am using the same code on a form which is derived from a base form, and running into a problem, in that the object returned in the sender parameter, although clearly a checkbox with a recognisable name, isn't any of the checkboxes in the array.
I verified this with:-
Private Sub cbxSpecimen_CheckedChanged( sender As System.Object, e As System.EventArgs) Handles cbxSpecimen.CheckedChanged
For i As Integer = 0 To checkbox_array.GetUpperBound(0) - 1
If checkbox_array(i).Equals(sender) Then
// set a breakpoint here
End If
Next i
End Sub
Can anyone shed any light on why this should work on a normal form, but not a derived-class form?
I verified this with:-
Private Sub cbxSpecimen_CheckedChanged( sender As System.Object, e As System.EventArgs)
Handles cbxSpecimen.CheckedChanged
For i As Integer = 0 To checkbox_array.GetUpperBound(0) - 1
If checkbox_array(i).Equals(sender) Then
// set a breakpoint here
End If
Next i
End Sub
Why checkbox_array.GetUpperBound(0) - 1? This will skip the last element in the array. Try:
For i As Integer = 0 To checkbox_array.GetUpperBound(0)
If checkbox_array(i).Equals(sender) Then
// set a breakpoint here
End If
Next i
Or
For i As Integer = 0 To checkbox_array.Length - 1
...
I have managed to get this to work by refilling the array of checkboxes inside the click event:-
Private Sub cbxSpecimen_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles cbxSpecimen.CheckedChanged
For i As Integer = 0 To check_boxes.GetUpperBound(0)
If check_box_array(i).Name = CType(sender, CheckBox).Name And
Not check_box_array(i).Equals(sender) Then
check_box_array(i) = CType(sender, CheckBox)
End If
Next i
' do useful work
End Sub
After the check box on the form has been stuffed back into the array, it remains there (so the second invokation for the same checkbox doesn't insert into the array a second time).
This seems like a ghastly hack to me, but I'll go with it for the time being.

Search ListBox elements in VB.Net

I'm migrating an application from VB6 to VB.Net and I found a change in the behavior of the ListBox and I'm not sure of how to make it equal to VB6.
The problem is this:
In the VB6 app, when the ListBox is focused and I type into it, the list selects the element that matches what I type. e.g. If the list contains a list of countries and I type "ita", "Italy" will be selected in the listbox.
The problem is that with the .Net version of the control if I type "ita" it will select the first element that starts with i, then the first element that starts with "t" and finally the first element that starts with "a".
So, any idea on how to get the original behavior? (I'm thinking in some property that I'm not seeing by some reason or something like that)
I really don't want to write an event handler for this (which btw, wouldn't be trivial).
Thanks a lot!
I shared willw's frustration. This is what I came up with. Add a class called ListBoxTypeAhead to your project and include this code. Then use this class as a control on your form. It traps keyboard input and moves the selected item they way the old VB6 listbox did. You can take out the timer if you wish. It mimics the behavior of keyboard input in Windows explorer.
Public Class ListBoxTypeAhead
Inherits ListBox
Dim Buffer As String
Dim WithEvents Timer1 As New Timer
Private Sub ListBoxTypeAhead_KeyDown(sender As Object, _
e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.A To Keys.Z, Keys.NumPad0 To Keys.NumPad9
e.SuppressKeyPress = True
Buffer &= Chr(e.KeyValue)
Me.SelectedIndex = Me.FindString(Buffer)
Timer1.Start()
Case Else
Timer1.Stop()
Buffer = ""
End Select
End Sub
Private Sub ListBoxTypeAhead_LostFocus(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.LostFocus
Timer1.Stop()
Buffer = ""
End Sub
Public Sub New()
Timer1.Interval = 2000
End Sub
Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles Timer1.Tick
Timer1.Stop()
Buffer = ""
End Sub
End Class
As you probably know, this feature is called 'type ahead,' and it's not built into the Winform ListBox (so you're not missing a property).
You can get the type-ahead functionality on the ListView control if you set its View property to List.
Public Function CheckIfExistInCombo(ByVal objCombo As Object, ByVal TextToFind As String) As Boolean
Dim NumOfItems As Object 'The Number Of Items In ComboBox
Dim IndexNum As Integer 'Index
NumOfItems = objCombo.ListCount
For IndexNum = 0 To NumOfItems - 1
If objCombo.List(IndexNum) = TextToFind Then
CheckIfExistInCombo = True
Exit Function
End If
Next IndexNum
CheckIfExistInCombo = False
End Function