1

I understand how to loop through regular controls on a form. For example, if I wanted to change the background color of all panels on a form to red, I would do this...

    Dim IndividualControl As Control
    For Each IndividualControl In Me.Controls
        If (TypeOf IndividualControl Is Panel) Then
            IndividualControl.BackColor = Color.Red
        End If
    Next IndividualControl

But let's say that instead of changing the properties of all the panels on a form, I want to change the properties of all of the web browser controls on a form (don't ask why I have several instances of the webbrowser control on a form -- it's a long story, and is simply what the project requires :)

So for example, if I wanted to change the "ScriptErrorsSuppressed" property to TRUE for all WebBrowser controls on a form, I assumed that the following code would work, but it doesn't (it just returns an error stating "ScriptErrorsSuppressed is not a member of System.Windows.Forms.Controls".

    Dim IndividualControl As Control
    For Each IndividualControl In Me.Controls
        If (TypeOf IndividualControl Is WebBrowser) Then
            IndividualControl.ScriptErrorsSuppressed = True
        End If
    Next IndividualControl

So... any ideas how to pull this off? Using VB2010 / Winforms

NotQuiteThereYet
  • 477
  • 3
  • 13
  • 25

1 Answers1

1

The error you're getting makes perfect sense, since you've declared IndividualControl to be of type Control, and objects of type Control don't have a ScriptErrorsSuppressed member.

Now, you may be saying to yourself, "I know that it does, because I know that IndividualControl is an object of type WebBrowser". Yes, you know that it does, but the compiler doesn't know that. The TypeOf operator only checks the type of the object and returns the result. It doesn't actually cast the object to a new type, nor does it redeclare the object to an object of the new type.

In fact, most of the time you use the TypeOf operator, it is to check and see if a cast is appropriate. You've got that part right here already, you just forgot to do the actual casting once you knew that the cast would succeed. The fix, then, is simple:

Dim IndividualControl As Control
For Each IndividualControl In Me.Controls
    If (TypeOf IndividualControl Is WebBrowser) Then
        ' We know that IndividualControl is of type WebBrowser now, so we can
        ' cast it directly to that type and be confident it will succeed.
        DirectCast(IndividualControl, WebBrowser).ScriptErrorsSuppressed = True
    End If
Next IndividualControl

Note that we used the VB.NET DirectCast operator here, which is acceptable because we have already verified that the cast is valid using the TypeOf operator. You could replace the DirectCast operator with the TryCast operator and then omit the TypeOf test. The code would perform in essentially the same way; pick whichever one makes the most sense for your scenario. For more information on the cast of cast operators in VB.NET, see this question. For DirectCast in particular, may I draw your attention to this informative post, which I couldn't agree more with.

Okay then, you're probably saying, I get how this works and I know how to fix my code. But—why did it work the first time when I tried to change the background color of a panel? I used exactly the same code!

Indeed you did. The catch is that the BackColor property is a property of the Control class, which is the declared type of IndividualControl. The compiler checks to see that IndividualControl has a BackColor property, sees that it does, and accepts your code. It doesn't see that it has a ScriptErrorsSuppressed property, so it rejected that code. Stated another way, the BackColor property is not unique to the Panel type, so you didn't need to perform the cast there.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Cody, much thanks for the detailed reply! :) I really appreciate it. I tried your code but got a syntax error on the 'DirectCast' line (it expects 2 arguments instead of 1). So then I tried it with 2 arguments (IndividualControl, WebBrowser) but it doesn't seem to work with that either. Any ideas? – NotQuiteThereYet Mar 18 '13 at 22:09
  • Nevermind that last comment Cody, I got it to work (I had the WebBrowser controls in a panel in the form, but when I moved them outside of the panel, all is good now). Thanks again! – NotQuiteThereYet Mar 18 '13 at 22:13
  • @NotQuiteThereYet Doh! Yeah I forgot you need to specify what you're casting it to. `DirectCast(IndividualControl, WebBrowser)` is the correct syntax, I'll update the answer. This should work just fine if the controls are in another container, like a panel. Your issue is simply that you're only iterating through `Me.Controls`, which is the *form*. You need a recursive loop if you want to loop through all of the controls in all of the container controls on the form. All containers have a `Controls` property. – Cody Gray - on strike Mar 18 '13 at 22:37
  • Yeah, I had forgotten the syntax for getting at container controls. Been a while since I've had a project that required that. I appreciate all your help :) – NotQuiteThereYet Mar 18 '13 at 22:55