简体   繁体   中英

How can I dispose of dynamically created controls?

I am dynamically creating controls on top of TabPages that are, of course, on a TabControl. I want to be able to dynamically dispose of these, too. How can I do that? Calling Clear on the TabControl's TabPages collection actually disposes the TabPages themselves, which defeats the purpose of "starting over" with new dynamically created controls on those pages.

Calling tabPageBla.Controls.Clear() is close to what I want, but it also disposes a container control that I have on each TabPage (FlowControlLayout) that I need to keep.

Is there a straightforward way to accomplish this (dispose only the dynamically-created controls, but not any of the others)?

UPDATE

Will this work - will grandchildren of TabControl1 also be found (children of the tab pages)?:

List<Control> ctrls = new List<Control>();
ctrls.AddRange(tabControl1.Controls);
foreach (var ctrl in ctrls)
{
    // Controls named "panelRowBla", "richTextBoxBla", and "pictureBoxBla" need to be retained
    string ctrlName = ctrl.Name;
    if ((ctrlName.Contains("panelRow")) ||
        (ctrlName.Contains("richTextBox")) ||
        (ctrlName.Contains("pictureBox")))
    {
        continue;
    }
}

UPDATE 2

That's odd; I could have sworn this was just compiling, but now I'm getting " Argument 1: cannot convert from 'System.Windows.Forms.Control.ControlCollection' to System.Collections.Generic.IEnumerable' "

(on the "AddRange()" line).

If you remove the control from the parent, you can explicitly Dispose it, ie:

 parent.Controls.Remove(theControl);
 ((IDisposable)theControl).Dispose();

Given your edits, you should be able to do:

var toRemove = tabControls1
      .Controls
      .Cast<Control>()
      .Where(c => !(c.Name.Contains("panelRow") || c.Name.Contains("richTextBox") || c.Name.Contains("pictureBox")))
      .ToList();

foreach(var c in toRemove)
{
     tabControls1.Controls.Remove(c);
     ((IDisposable)c).Dispose();
}

This will remove all of the controls from the tabControl1 which don't match your filter.

There is no way to tell if the control was created in the designer or dynamically. But what you can do, is to create a list of all the controls, which exist at the very start (controls which were created in the designer).

Create a new list to the class' root, to hold all the "original" controls:

List<Control> DesignerControls;

Use this modified PsychoCoder's method ( https://stackoverflow.com/a/3426721/2538037 ) to list all controls (including controls inside controls):

public IEnumerable<Control> GetAll(Control control)
{
   var controls = control.Controls.Cast<Control>();

   return controls.SelectMany(ctrl => GetAll(ctrl))
                  .Concat(controls);
}

Before you have added any controls dynamically, run this line (for example in the constructor):

DesignerControls = GetAll(this).ToList();

Then add this static method for disposing the dynamically created controls:

public static bool DisposeDynamicObjects(List<Control> NonDynamicControls, List<Control> ControlsToDispose)
{
   try
   {
      for (int i = 0; i < ControlsToDispose.Count; i++)
      {
         if (ControlsToDispose[i] != null &&
             !ControlsToDispose[i].IsDisposed &&
             !NonDynamicControls.Contains(ControlsToDispose[i]))
         {
            ControlsToDispose[i].Dispose();
            --i;
         }
      }
      return true;
   }
   catch (Exception ex) { MessageBox.Show(ex.Message); return false; }
}

When you want to dispose dynamically created controls, use this:

DisposeDynamicObjects(DesignerControls, GetAll(tabControl1).ToList());

The code above disposes all dynamically created controls inside tabControl1.Controls . You can replace the tabControl1 with other controls, like this for example, so all dynamically created controls are deleted from the whole form.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM