removing dynamically created controls C#

I have a program that adds a series of "blips" to a graph:

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.SetChildIndex(blip, 0);
  1. How do I have a button clear all of the "blips" that have been created with this code?

  2. Is there a way to change a blip's background color when its name is equal to a certain callsign? Each blip is associated with a selection in a ListBox, and I would like to change the blip's color when the user selects it.


Everybody is forgetting a very important detail: you have to Dispose() the control or it will leak forever:

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

I'll put some more emphasis on the forever clause, lots of clamor about it in the comments, the Control class does not behave like any other .NET class. A Control is kept alive by its Handle property. Which stores the native Windows handle. As long as the native window exists, the Control object cannot be destroyed.

This requires the object to be kept alive artificially when you use Clear() or Remove() and remove the control from its parent. Winforms uses the so-called "parking window" as the host of such controls. It is a normal native window like any other, it is just not visible. Its job is to be the parent of such orphaned controls.

The parking window permits lots of neat tricks that are normally very hard to do in Windows. You can for example turn the ShowInTaskbar property on and off at runtime. A property of a window that can normally only be specified when you create the window (WS_EX_APPWINDOW style, specified in the CreateWindowEx() call). Winforms can do it even after you created the window by moving the controls of the form to the parking window, destroying the window, creating it again and moving the controls back. Neat.

But with the not-so-neat hangup that's the topic of this answer, if you remove the control and don't call its Dispose() method then it will continue to survive on the parking window. Forever. A true leak. Nothing that the garbage collector can do about it, it sees a valid reference to the object. A pretty gross violation of the IDisposable contract, calling Dispose() is optional but it is not for the Control class.

Luckily such a bug is pretty easy to diagnose, it doesn't require any special tooling, you can see the leak in Task Manager's Processes tab. Add the "USER Objects" column.


This will remove all of the PictureBox controls from the particular container (i assume a graph in your case).

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


You might want to add the blip to a List and then when the user clicks the "Clear" button, just iterate over the list, remove the blip from the Controls collection, then clear the list.

In terms of changing the background color, why don't you just use an if statement?

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

It seems Hans Passant forgot a very important detail, too (or perhaps he was just adding to the existing answers, not submitting a full answer). At any rate, here's what I had to do both to invisiblize and dispose my dynamic controls:

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


 ? Add columns to a datatable in c#?
 ? ASP NET - C#: Access controls by Id
 ? Add a bunch of controls dynamically to screen in iOS
 ? Can't dynamically add new literal to ASP.NET Panel Control
 ? Add dynamic ASP.NET controls via a DropDownList to the page
 ? WinForm: control won't add to a panel
 ? ASP.NET refresh Update Panel
 ? Create textbox dynamically without postback
 ? Second button Event is not happening in Update panel in aspx page
 ? ASP.Net: click event for dynamic button in dynamically created nested update panel is not raised