Checkbox returned in Event Handler isn't one on form - vb.net

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.

Related

Infinite loop is causing the form to not show up vb

I have an infinite loop in this sub because I want the program to keep testing this process to see if the variable has changed. When I run the program in the debugger, nothing shows up, including the form however when I removed the infinite loop from the program, the form showed up again. Does anyone know why this is happening? I should also mention I've tried a DO LOOP as well. Can anyone help?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim greenCount As Integer
Dim looptest As Boolean = True
While looptest = True
For Each control In Me.Controls.OfType(Of Button)
If control.BackColor = Color.Lime Then
greenCount += 1
End If
Next
txtFielder.Text = greenCount.ToString
End While
End Sub
You need to get rid of all that code regardless. Depending on how you're changing the BackColor of those Buttons in the first place, updating the lime count might be best done there. Otherwise, you should be handling the appropriate event, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
If DirectCast(sender, Button).BackColor = Color.Lime Then
limeButtonCount += 1
Else
limeButtonCount -= 1
End If
TextBox1.Text = limeButtonCount.ToString()
End Sub
Note that this code assumes that there are only two possible BackColor values and that all Buttons are not lime by default. If your scenario is a bit more complex than that then you may need to change a code a little, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
limeButtonCount = Controls.OfType(Of Button)().Count(Function(b) b.BackColor = Color.Lime)
TextBox1.Text = limeButtonCount.ToString()
End Sub
Form.Load occurs before a form is displayed for the first time.
This means that you'll never see your form as long as you loop in this event. You probably want to use the Shown event instead.

Visual Basic- Loop to make listbox update as checkbox is checked

I'm having trouble having the listbox update as the checkbox is checked. I have a total of 8 "test_location" check boxes and I want the listbox to add items to "Steps_Queue_List" and store "1" in the "Test_Locations" array when the location is checked. Also want to clear the list when the checkbox is unchecked. This works so far but I would much prefer to learn how to make a loop for this:
Private Sub Location_CheckBox_1_CheckedChanged(sender As Object, e As EventArgs) Handles Location_CheckBox_1.CheckedChanged
If Location_CheckBox_1.Checked Then
Test_Locations(0) = 1
Steps_Queue_List.Items.Add("test for location" & 1, 1)
ElseIf Location_CheckBox_1.Checked = False Then
Test_Locations(0) = 0
Steps_Queue_List.Items.RemoveAt(0)
End If
End Sub
Private Sub Location_CheckBox_2_CheckedChanged(sender As Object, e As EventArgs) Handles Location_CheckBox_2.CheckedChanged
If Location_CheckBox_2.Checked Then
Test_Locations(1) = 1
Steps_Queue_List.Items.Add("test for location" & 2, 2)
ElseIf Location_CheckBox_2.Checked = False Then
Test_Locations(1) = 0
Steps_Queue_List.Items.RemoveAt(0)
End If
End Sub
Private Sub Location_CheckBox_3_CheckedChanged(sender As Object, e As EventArgs) Handles Location_CheckBox_3.CheckedChanged
If Location_CheckBox_3.Checked Then
Test_Locations(2) = 1
Steps_Queue_List.Items.Add("test for location" & 3, 3)
ElseIf Location_CheckBox_3.Checked = False Then
Test_Locations(2) = 0
Steps_Queue_List.Items.RemoveAt(0)
End If
End Sub
Thanks in advance.
You don't need a loop but you can just handle everything in a single method.
Set the property Tag of your Checkboxes to a progressive value starting from 1 to 8 matching the text value you want to be displayed in the listboxes.
Then setup an event handler that manages all the CheckBoxChanged events for all the CheckBox.
In this event handler retrieve the tag and use it to address the array index and the listbox to update
' Handle all Checkbox changed with the same handler
Private Sub OnCheckBoxChanged(sender As Object, e As EventArgs)
Handles Location_CheckBox_1.CheckedChanged,Location_CheckBox_2.CheckedChanged,
Location_CheckBox_3.CheckedChanged,Location_CheckBox_4.CheckedChanged,
Location_CheckBox_5.CheckedChanged,Location_CheckBox_6.CheckedChanged,
Location_CheckBox_7.CheckedChanged,Location_CheckBox_8.CheckedChanged
' Discover which checkbox has been clicked
Dim chk = DirectCast(sender, CheckBox)
' Now read the value of the Tag property of that checkbox
Dim idx = Convert.ToInt32(chk.Tag)
If chk.Checked Then
Test_Locations(idx - 1) = 1
Steps_Queue_List.Items.Add("test for location" & idx, idx)
Else
Test_Locations(idx - 1) = 0
Steps_Queue_List.Items.RemoveAt(0)
End If
End Sub

Visual basic empty text box throws exception

The code below is a program to calculate the BMI using text boxes. I am having an issue however that when I clear one of the text boxes it will throw an exception and freeze the program. I was wondering if anyone had an answer on how to prevent this. I already tried setting my variables to 0 and 1 to see if that was the issue but it does not appear to be.
Private Sub tboxWeight_TextChanged(sender As Object, e As EventArgs) Handles tboxWeight.TextChanged
Weight = 0
Weight = Convert.ToInt64(tboxWeight.Text)
End Sub
Private Sub tboxHFeet_TextChanged(sender As Object, e As EventArgs) Handles tboxHFeet.TextChanged
Height_feet = 0
Height_feet = Convert.ToInt64(tboxHFeet.Text)
Get_BMI(1)
End Sub
Private Sub tboxHInch_TextChanged(sender As Object, e As EventArgs) Handles tboxHInch.TextChanged
Height_Inches = 0
Height_Inches = Convert.ToInt64(tboxHInch.Text)
Get_BMI(1)
End Sub
Private Sub tboxAge_TextChanged(sender As Object, e As EventArgs) Handles tboxAge.TextChanged
Age = Convert.ToDouble(tboxAge.Text)
End Sub
Function Get_BMI(ByVal j As Integer) As Double
BMI = (Weight / (Height_Inches + (Height_feet * 12) ^ 2) * 703)
tboxBMI.Text = Convert.ToString(BMI)
Exit Function
End function
It is because you set a textbox into an integer field, so when the textbox is empty it will throw exception because the textbox doesn't contain a number.
Try using If else statement for each textboxes.
String.IsNullOrEmpty function will be sufficient.
Good/Best practice says, you need to validate the data before performing calculation i.e. Get_BMI(). Below code snippet will help you.
Dim textBoxValue As String
If Not String.IsNullOrEmpty(textBoxValue) Then
If IsNumeric(textBoxValue) Then
End If
End If

Validating textbox when enter button is pushed

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

Incrementing Label Value when a button is clicked

I have tried converting using CInt, TryParse, Convert.Int32, etc but nothing worked. I just need to display the total votes of the candidated when a button btnVote is clicked and display the result when I click btnResult. I've tried searching on the net also but still no luck so I came up to this website and hopefully I could solve my problem with my program in VB.net
Below is my code:
Public Class Presidential_Election
Private Sub btnVote_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnVote.Click
If cboCandidates.Text = "NOLI" Then
lblNoli.Text = Integer.Parse(lblNoli.Text) + 1
ElseIf cboCandidates.Text = "VAL" Then
lblVal.Text = (CInt(lblVal.Text) + 1).ToString
ElseIf cboCandidates.Text = "LESTER" Then
lblLester.Text = CInt(lblLester.Text) + 1
ElseIf cboCandidates.Text = "GWAPO" Then
lblGwapo.Text = CInt(lblGwapo.Text) + 1
End If
End Sub
Private Sub btnResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResult.Click
lblNoli.Visible = True
lblVal.Visible = True
lblLester.Visible = True
lblGwapo.Visible = True
End Sub
End Class
I would set an integer counter for each candidate. Set these to 0 and then increment them as they receive a vote. When you display the results just bind the text of the label to its respective counter and make it visible. This way, you don't have to keep referencing label.text.
If you haven't set the label text to be 0 at the beginning, using CInt would definitely throw an error. You have two options :
set all labels text to 0 and keep using CInt, or
use Val()
Example :
lblGwapo.Text = Val(lblGwapo.Text) + 1