在C#中删除动态创建的控件

时间:2010-01-06 16:09:20

标签: c# dynamic controls

我有一个程序可以在图表中添加一系列“blip”:

PictureBox blip = new PictureBox();
blip.Location = new Point(blipHours, blipAltitude);
blip.Size = new Size(6, 6);
blip.BackColor = System.Drawing.Color.Lime;
blip.Text = "";
blip.Name = callsign;
this.Controls.Add(blip);
this.Controls.SetChildIndex(blip, 0);
  1. 如何清除使用此代码创建的所有“blip”按钮?

  2. 当名称等于某个callsign时,有没有办法更改blip的背景颜色?每个blip都与ListBox中的选择相关联,我想在用户选择时更改blip的颜色。

5 个答案:

答案 0 :(得分:25)

每个人都忘记了一个非常重要的细节:你必须Dispose()控件,否则它将永远泄漏:

for (int ix = this.Controls.Count - 1; ix >= 0; ix--) {
    if (this.Controls[ix] is PictureBox) this.Controls[ix].Dispose();
}

我将更多地强调 forever 子句,在注释中有很多关于它的喧嚣,Control类的行为与其他任何.NET类都不同。控件由其Handle属性保持活动状态。哪个存储本机Windows句柄。只要存在本机窗口,就无法销毁Control对象。

当您使用Clear()或Remove()并从其父级中删除控件时,这需要对象保持人工。 Winforms使用所谓的“停车窗口”作为此类控件的主机。这是一个像任何其他窗口一样的普通本机窗口,它只是不可见。它的工作是成为这种孤立控制的父母。

停车窗口允许在Windows中通常很难做到的许多巧妙的技巧。例如,您可以在运行时打开和关闭ShowInTaskbar属性。窗口的属性,通常只能在创建窗口时指定(WS_EX_APPWINDOW样式,在CreateWindowEx()调用中指定)。 Winforms甚至可以在您创建窗口后通过将窗体的控件移动到停放窗口,破坏窗口,再次创建窗口并将控件移回原来来完成。整齐。

但是,如果您删除控件并且调用其Dispose()方法,那么这个答案的主题不那么整洁,那么它将继续在停车时生存窗口。永远。一个真正的泄漏。垃圾收集器无法对其做任何事情,它会看到对象的有效引用。严重违反IDisposable合同,调用Dispose()是可选的,但Control类的不是

幸运的是,这样的错误很容易诊断,它不需要任何特殊工具,您可以在任务管理器的进程选项卡中看到泄漏。添加“USER Objects”列。

答案 1 :(得分:4)

this.Controls.Clear();

答案 2 :(得分:2)

您可能希望将blip添加到List中,然后当用户单击“Clear”按钮时,只需遍历列表,从Controls集合中删除blip,然后清除列表。

在更改背景颜色方面,为什么不使用if语句?

blip.BackColor = callsign == "SpecialSign"? System.Drawing.Color.Red : System.Drawing.Color.Lime

答案 3 :(得分:2)

这将删除特定容器中的所有PictureBox控件(假设您的情况下是图形)。

 for (int i = this.Controls.Count - 1; i >= 0; i--)
            {
                PictureBox control = this.Controls[i] as PictureBox;
                if (control == null)
                    continue;

                control.Dispose();
            }

答案 4 :(得分:0)

看起来汉斯帕森特也忘记了一个非常重要的细节(或许他只是在增加现有的答案,而不是提交一个完整的答案)。无论如何,我必须做的就是隐形和处理我的动态控件:

Panel p = tp.Controls[panelName] as Panel;
p.Controls.Clear();
for (int i = 0; i < p.Controls.Count; i++)
{
    p.Controls[i].Dispose();
}