如何处理动态创建的控件?

时间:2014-06-03 18:26:26

标签: c# winforms dynamic dispose

我在TabPages上动态创建控件,当然是在TabControl上。我希望能够动态处理这些。我怎样才能做到这一点?在TabControl的TabPages集合上调用Clear实际上会释放TabPages本身,这会使这些页面上新动态创建的控件“重新开始”的目的失效。

调用tabPageBla.Controls.Clear()接近我想要的,但是它还处理了我需要保留的每个TabPage(FlowControlLayout)上的容器控件。

有没有直接的方法来实现这一点(只处理动态创建的控件,但不处理任何其他控件)?

更新

这是否有效 - 是否还会找到TabControl1的孙子(标签页的子项)?:

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;
    }
}

更新2

那很奇怪;我可以发誓这只是编译,但现在我得到“参数1:无法从'System.Windows.Forms.Control.ControlCollection'转换为System.Collections.Generic.IEnumerable'

(在“AddRange()”行上。)

2 个答案:

答案 0 :(得分:4)

如果从父级删除控件,则可以显式Dispose,即:

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

鉴于您的编辑,您应该能够:

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();
}

这将删除tabControl1中与您的过滤器不匹配的所有控件。

答案 1 :(得分:1)

无法判断控件是在设计器中创建还是动态创建。但你可以做的是创建一个控件的列表,这些控件一开始就存在(控件在设计器中创建)。

为班级创建一个新列表&#39; root,持有所有&#34;原创&#34;控制:

List<Control> DesignerControls;

使用此修改后的PsychoCoder方法(https://stackoverflow.com/a/3426721/2538037)列出所有控件(包括控件内的控件):

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

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

在动态添加任何控件之前,请运行此行(例如在构造函数中):

DesignerControls = GetAll(this).ToList();

然后添加此静态方法来处理动态创建的控件:

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; }
}

如果要处置动态创建的控件,请使用:

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

上面的代码将所有动态创建的控件都放在tabControl1.Controls中。您可以将tabControl1替换为其他控件,例如this,以便从整个表单中删除所有动态创建的控件。