Link to home
Start Free TrialLog in
Avatar of tentavarious
tentavarious

asked on

How do I remove/dispose all controls in a flow layout panel visual studio 2008?

Experts this is really baffling me.  I have a visual studio 2008 windows form.  When the form loads I dynamically build 17 panels, I also add controls to those same panels, finally I add those panels to a flow layout panel.  The reasoning behind this, is the 17 panels represents a 1 record in our database, I will not know the details of the panel until the query is ran.  When the record is completed via database side I need to remove those 17 panels and eventually build 17 more panels.  If you look at the code below I thought i could just loop through all the controls in the panel and dispose them.  This is not the case not all the controls get disposed.  When I click the button only 9 get disposed, then the second click 4 get disposed, then 2, then 1, then 1.  Totalling 17 controls in all.  I need to click the button 5 times to completely dispose all the controls, why is this and how come the don't get diposed the first time through?  If you need the code showing how I dynamically build the panels let me know.
Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
        clear_controls(Me.flpbase) 'Flow layout panel containing controls I want to dispose
    End Sub
 
    Sub clear_controls(ByVal ctrl As Control)
        Dim frmctrl As Control
        For Each frmctrl In ctrl.Controls
             DirectCast(frmctrl, Panel).Dispose()
        Next
    End Sub

Open in new window

Avatar of abel
abel
Flag of Netherlands image

The for-each calls an enumerator. When you dispose a control, the enumerator will move one control upwards (because you kicked one out in the middle of the loop). This is why enumerators are not handy to use when inside the loop you are changing the list the enumerator is walking over.

To change this behavior, do the reverse. Use an old-school for-loop that walks backwards from the top and you will see that it actually does work.
Like this:

' walking the list backwards '
For iIdx As Integer = Me.Controls.Count To 0 Step -1
    If TypeOf Me.Controls(iIdx) Is Panel Then
        CType(Me.Controls(iIdx), Panel).Dispose()
    End If
Next

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tentavarious
tentavarious

ASKER

Thanks that solved it
> Thanks that solved it

glad it helped :)
Avatar of Mike Tomlinson
Another option:

        Dim ctls As New List(Of Control)
        ctls.AddRange(Me.flpbase.Controls.OfType(Of Panel).ToArray)
        For Each ctl As Control In ctls
            ctl.Dispose()
        Next
@Idle_Mind: nice alternative!