Properly disposing/closing an user control

12,844

Solution 1

Use this loop before calling panel1.Controls.Clear() and be sure that the Dispose() method in the user controls are in turn disposing of any disposable resources.

foreach (Control control in panel1.Controls)
{
   control.Dispose();
}

Solution 2

A for each loop will not do the job. Since after each dispose the elements and indexes are changed.

You need a while loop disposing the top most control each time.

In the following code that I use, I have a panel with user controls in it. I go into the first control and dispose of its controls then dispose of the control itself.

After disposing of all the controls trigger a clear to reset the index.

While pnlMain.Controls.Count > 0

    While pnlMain.Controls(0).Controls.Count > 0
        pnlMain.Controls(0).Controls(0).Dispose()
    End While

    pnlMain.Controls(0).Dispose()
End While
pnlMain.Controls.Clear()

Solution 3

I do this enough with dynamic content that i have added this method to my base-page class:

/// <summary>
/// Dispose a control and all its children
/// </summary>
public void DisposeControl(Control c)
{
    if (null != c)
        using (c)
            DisposeChildControlsOf(c);
}

/// <summary>
/// Dispose (and remove) all the children of a control
/// </summary>
public void DisposeChildControlsOf(Control c)
{
    if (null != c)
        if (null != c.Controls)
            while (c.Controls.Count > 0)
            {
                Control child = c.Controls[0];
                c.Controls.RemoveAt(0);
                DisposeControl(child);
            }
}

It's recursive too. And then call it like so (if you don't own the control yourself):

DisposeChildControlsOf(panel1);

or

DisposeControl(myDynamicallyGeneratedControl);
Share:
12,844
Kharlos Dominguez
Author by

Kharlos Dominguez

Updated on June 04, 2022

Comments

  • Kharlos Dominguez
    Kharlos Dominguez about 2 years

    I have a Windows Form screen with a menu bar docked at the left-hand side on the form, similar to the one of Outlook 2003, and a panel taking the rest of the right-hand side of the form.

    My left menu contains items. Upon clicking on those items, I want to load the appropriate user control (acting as "sub-forms") on the right-hand side panel. I have managed to do that and it is working well.

    The worry I have though is whether or not my usercontrols are being disposed properly or if they remain on memory when the user clicks another menu item (and as such, loads another usercontrol/subform).

    The code is similar to this:

        private void ultraExplorerBar1_ItemClick(object sender, Infragistics.Win.UltraWinExplorerBar.ItemEventArgs e)
        {
            panel1.Controls.Clear();
    
            if (e.Item.Key == "Action")
            {
                ActionUserControl subForm = new ActionUserControl();
                panel1.Controls.Add(subForm);
                subForm.Show();                
            }
            else if (e.Item.Key == "Options")
            {
                OptionsUserControl subForm = new OptionsUserControl();
                panel1.Controls.Add(subForm);
                subForm.Show();
            }
        }
    

    I am not sure if the panel1.Controls.Clear() I'm calling at the beginning of the method is enough for the usercontrols not being used anymore to be garbage-collected in due-time?

    To my understanding, there shouldn't be any reference left to it in the application once cleared from the panel but I am not sure if I should be doing something else or of a reasonably lightweight tool I could use to confirm that my subforms are disposed as they should and that it doesn't cause some kind of memory/resources leak?