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

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

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的颜色。

每个人都忘记了一个非常重要的细节:你必须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”列。

 this.Controls.Clear(); 

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

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

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

这将从特定容器中删除所有PictureBox控件(我假设你的情况下有一个图形)。

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

似乎Hans Passant也忘记了一个非常重要的细节(或许他只是添加了现有的答案,而不是提交完整的答案)。 无论如何,这是我必须做的两件事来隐形和处理我的动态控件:

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