Search code examples
vb.netcontrolsgroupbox

Detect when any of the controls within a Group Box has changed


I have an 'Apply' button on a form which initially has the property Enabled = False, but when a control within any GroupBox on the from is changed Enabled = True should be set.

I have several GroupBox controls on the form, and I was hoping that I could simply check if a control within any of these had changed. However, while it seems you can hook to the ControlAdded and ControlRemoved events, there is no ControlChanged event.

So I'm currently setting this up as below (there are a lot more than 5 controls to check in reality).

Is there a more efficient way of doing this, as I can see this causing issues in the future (if options are ever added to a Group for example)? Thanks.

Private Sub ControlChanged(sender As Object,
                           e As EventArgs) Handles txtUsername.KeyUp,
                                                   chkRestoreIEFavourites.CheckedChanged,
                                                   chkRestoreNicknames.CheckedChanged,
                                                   chkRestoreDesktop.CheckedChanged,
                                                   chkRestoreQuickLaunch.CheckedChanged
    Me.btnApply.Enabled = True
End Sub

Solution

  • Alas, I've figured out a way of doing this...

    The below now adds handlers (on Shown) so that if any CheckBox or TextBox within a GroupBox on the form is changed, the Apply button is set to Enabled = True. I also remove the handles when the from is Closing.

    Whether this is the best way of doing it I don't know, but for now it's the only way that I know. Comments welcome!

    Private Sub formSettings_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SetupChangeHandlers()
    End Sub
    
    Private Sub formSettings_Closing(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Closing
        SetupChangeHandlers(Remove:=True)
    End Sub
    
    Private Sub SetupChangeHandlers(Optional ByVal Remove As Boolean = False)
    
        For Each GroupBox As GroupBox In Me.sptSettings.Panel2.Controls.OfType(Of GroupBox)() _
                                           .OrderBy(Function(b) b.TabIndex)
            For Each Control As Control In GroupBox.Controls.OfType(Of Control)() _
                                           .OrderBy(Function(b) b.TabIndex)
    
                If TypeOf Control Is CheckBox Then
                    Dim Checkbox = CType(Control, CheckBox)
                    If Not Remove Then : AddHandler Checkbox.CheckedChanged, AddressOf GroupBoxControl_Changed
                    Else : RemoveHandler Checkbox.CheckedChanged, AddressOf GroupBoxControl_Changed
                    End If
    
                ElseIf TypeOf Control Is TextBox Then
                    Dim TextBox = CType(Control, TextBox)
                    If Not Remove Then : AddHandler TextBox.TextChanged, AddressOf GroupBoxControl_Changed
                    Else : RemoveHandler TextBox.TextChanged, AddressOf GroupBoxControl_Changed
                    End If
    
                ElseIf TypeOf Control Is MaskedTextBox Then
                    Dim MaskedTextBox = CType(Control, MaskedTextBox)
                    If Not Remove Then : AddHandler MaskedTextBox.TextChanged, AddressOf GroupBoxControl_Changed
                    Else : RemoveHandler MaskedTextBox.TextChanged, AddressOf GroupBoxControl_Changed
                    End If
    
                End If
            Next
        Next
    
    End Sub
    

    Note that you will need to import System.Linq and System.Windows.Forms to use this solution.