.netvb.netwinforms

Method won't modify controls within form when called from a usercontrol


I have a method sub inside my main form that when called, it should disable the buttons within the form. For some reason, when I try to call this method from a usercontrol within the main form, it will not disable the buttons. Despite this, it will still run all other code within the method without an issue, so I am sure that the method is being called correctly.

I have attempted various ways to get this to work and I have found that if I call the method within the form itself instead, it will disable the buttons, though this is not what I intend to do.

This is the method I coded below:

Public Sub ChangeButtonAccessibility(switch As Boolean)
    If switch = True Then
        MessageBox.Show("TEST")
        btnAudioMethod.Enabled = False
        btnVideoMethod.Enabled = False
        btnDocumentMethod.Enabled = False
        btnImageMethod.Enabled = False
    Else
        MessageBox.Show("TEST2")
        btnAudioMethod.Enabled = True
        btnVideoMethod.Enabled = True
        btnDocumentMethod.Enabled = True
        btnImageMethod.Enabled = True
    End If
End Sub

It is being called using:

ChangeButtonAccessibility(True)

As you can see, I placed some message boxes to test this and found that they will appear when the method is called from the usercontrol but won't disable the buttons. Again, if I call the same method from the form instead of the usercontrol, it will disable them.

It also will not work if I directly modify the buttons from the usercontrol instead of calling a method, in fact I originally tried doing that before switching to a method call.

I find this very strange. There may be a simple explanation to this, but after looking everywhere online I cannot find an answer.


Solution

  • There are two common reasons you might have this issue:

    1. If ChangeButtonAccessibility() is called from another thread, you need to Invoke when setting control properties. You cannot set them directly, because the control memory belongs to the main UI thread. Certain kinds of control events can cause this in normal event methods, or sometimes when you go between different forms, and you can check by using the InvokeRequired property.

    2. Changing control properties does NOT immediately update the control on the screen. Rather, it goes through the Windows message pump in order to raise a Paint event before controls are redrawn. Until the code that calls your method returns execution flow back to the main message loop, you won't be able to see any changes. In other words, the method for the code that calls this method has to actually finish before you can see the changes.

    Both of these issues are also often better solved by rethinking the design a bit.


    Finally, as a side issue from the question we can simplify the code to reduce the size of the method by half:

    Public Sub ChangeButtonAccessibility(switch As Boolean)
        MessageBox.Show(If(switch, "TEST", "TEST2"))
        switch = Not switch  
        btnAudioMethod.Enabled = switch
        btnVideoMethod.Enabled = switch
        btnDocumentMethod.Enabled = switch
        btnImageMethod.Enabled = switch
    End Sub
    

    And we can simplify it even further with a better name for the input boolean that avoids the need for negation.