Search code examples
vb.netformscheckboxtextbox

Disable textboxes with the corresponding checkboxes in VB.net


Public Class Form1

    Dim controlNames() As String = {"Tea", "Cola", "Coffee", "Orange", "Water", "VanillaCone", "VanillaShake", "StrawberryShake", "ChocolateMilkshake", "Fries", "Salad", "Hamburger", "OnionRings", "ChickenSalad", "FishSandwich", "CheeseSandwich", "ChickenSandwich"}


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

        For Each ctrl As Control In Me.Panel2.Controls

            If TypeOf ctrl Is TextBox Then
                    ctrl.Enabled = False
                End If

        Next

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs)
        For i = 0 To 16
            For Each ctrl As Control In Me.Panel2.Controls
                If TypeOf ctrl Is CheckBox Then
                    If ctrl.Name = "chk" & controlNames(i) Then
                        If DirectCast(ctrl, CheckBox).CheckState = CheckState.Checked Then
                            If TypeOf ctrl Is TextBox Then
                                If ctrl.Name = "txt" & controlNames(i) Then
                                    ctrl.Enabled = True
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub

I have a VB.NET assignment and I am attempting to enable textboxes based on whether or not the checkbox with the same name was checked. This is my code so far and it obviously doesn't work. What I want to do essentially:

All textboxes start as disabled. Then, textboxes only get enabled if the corresponding checkboxes are checked. For example, if chkTea is checked, then it enables txtTea.

I am aware I can copy paste something like "if chkTea = checked then txt.tea = enabled". I do not want to do this as this seems like a poor way to go about this. I want to know if I can do something like my barely readable code shows.


Solution

  • If you're renaming all your controls to something different to the default name with a number, this code should work just fine.

    You dont need a timer, it just fires when any of the CheckBoxes have their state changed.

    In the example code, I've created a CheckedChanged handler and set it to handle some of the CheckBoxes (You'll want to add all those you want to handle). If you click on any of these CheckBoxes, the handler will fire. The handler then passes which checkbox has been changed to the SyncTextBoxWithCheckBoxState method. This then finds the matching textbox using the FindMatchingCheckBox method and sets the .Enabled state of the Text box to the same as the .Checked state of the CheckBox

    Private Sub chkTea_CheckedChanged(sender As Object, e As EventArgs) Handles chkTea.CheckedChanged, chkCoffee.CheckedChanged, chkCola.CheckedChanged, chkOrange.CheckedChanged, chkTea.CheckedChanged, chkVanillaCone.CheckedChanged, chkVanillaCone.CheckedChanged, chkWater.CheckedChanged
        SyncTextBoxWithCheckBoxState(CType(sender, CheckBox))
    End Sub
    
    Private Sub SyncTextBoxWithCheckBoxState(chkBox As CheckBox)
        Dim txtBox As TextBox = FindMatchingTextBox(chkBox)
        txtBox.Enabled = chkBox.Checked
    End Sub
    
    Private Function FindMatchingTextBox(chkbox As CheckBox) As TextBox
        For Each ctrl As Control In Panel2.Controls
            If ctrl.GetType Is GetType(TextBox) And ctrl.Name.Contains(chkbox.Name.Substring(3)) Then
                Return CType(ctrl, TextBox)
            End If
        Next
        Return Nothing
    End Function
    

    EDIT

    To have the code target more than one panel, add all the checkboxes you want to detect to the event handler like before, and in the FindMatchingTextBox method, just add another loop around the existing one to loop through each panel. Like so ..

    Private Function FindMatchingTextBox(chkbox As CheckBox) As TextBox
        'This is the new loop which loops through the two panels. It's
        'a bit quick and dirty, but it works
        For Each pnl As Panel In New Panel() {Panel2, Panel3}
        'In this line note that the reference to Panel2 now refers to pnl
            For Each ctrl As Control In pnl.Controls
                If ctrl.GetType Is GetType(TextBox) And ctrl.Name.Contains(chkbox.Name.Substring(3)) Then
                    Return CType(ctrl, TextBox)
                End If
            Next
        'End point of the new loop
        Next
        Return Nothing
    End Function