2010-01-06 16 views
6

tengo un programa que agrega una serie de "baches" a un gráfico:Extracción controles creados dinámicamente en C#

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. ¿Cómo tengo un botón de borrar todos los "baches" que tienen creado con este código?

  2. ¿Hay alguna manera de cambiar el color de fondo de un blip cuando su nombre es igual a un determinado callsign? Cada blip está asociado con una selección en un ListBox, y me gustaría cambiar el color del blip cuando el usuario lo selecciona.

Respuesta

24

Todo el mundo está olvidando un muy detalle importante: tienes que Dispose() el control o que se escapará para siempre:

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

Voy a poner un poco más de énfasis en el forever cláusula, hay mucho clamor al respecto en los comentarios, la clase Control no se comporta como cualquier otra clase .NET. Un control se mantiene vivo por su propiedad Handle. Que almacena el manejo nativo de Windows. Mientras exista la ventana nativa, el objeto Control no se puede destruir.

Esto requiere que el objeto se mantenga con vida artificialmente cuando utiliza Borrar() o Eliminar() y elimina el control de su elemento primario. Winforms usa la llamada "ventana de estacionamiento" como el anfitrión de tales controles. Es una ventana nativa normal como cualquier otra, simplemente no es visible. Su trabajo es ser el padre de dichos controles huérfanos.

La ventana de estacionamiento permite muchos trucos aseados que normalmente son muy difíciles de hacer en Windows. Puede, por ejemplo, activar y desactivar la propiedad ShowInTaskbar en tiempo de ejecución. Una propiedad de una ventana que normalmente solo se puede especificar al crear la ventana (estilo WS_EX_APPWINDOW, especificado en la llamada a CreateWindowEx()). Las formas de Win pueden hacerlo incluso después de haber creado la ventana moviendo los controles del formulario a la ventana de estacionamiento, destruyendo la ventana, volviéndola a crear y moviendo los controles hacia atrás. Ordenado.

Pero con el hang-up no tan lindo que es el tema de esta respuesta, si elimina el control y no llame a su método Dispose(), entonces continuará sobreviviendo en la ventana de estacionamiento. Siempre. Una verdadera filtración. Nada que el recolector de basura pueda hacer al respecto, ve una referencia válida al objeto. Una violación bastante grave del contrato IDisposable, llamando a Dispose() es opcional, pero es no para la clase Control.

Afortunadamente, este error es bastante fácil de diagnosticar, no requiere ninguna herramienta especial, puede ver la fuga en la pestaña Procesos del Administrador de tareas. Agregue la columna "Objetos del USUARIO".

+1

+ 1..gracias por eso, lo olvidé por completo. de hecho controla el método de eliminación de llamadas parent.Controls.Remove (this) –

+1

No se filtrará para siempre ... solo se filtrará hasta que aparezca el recolector de basura ... y con suerte el destructor de PictureBox incluye una llamada a Dispose. – Nick

+1

@Stan R - ¿Lo hace? Genial ... ¡No lo sabía! – Nick

4
this.Controls.Clear(); 
+2

Opcionalmente, debido a que los controles se crean dinámicamente, el botón "Borrar" podría simplemente reconstruir el control sobre una devolución de datos completa con Nada en él. – NotMe

+0

esto eliminará todos los controles, independientemente de si son PictureBox o no. –

+0

esto borra todos los controles. Solo quiero borrar los controles "blip" que se crearon. – Brodie

2

Es posible que desee añadir el bache a una lista y luego, cuando el usuario hace clic en el botón "Borrar", simplemente iterar sobre la lista, eliminar el eco de la colección Controls, a continuación, desactive la lista .

En cuanto a cambiar el color de fondo, ¿por qué no utiliza una instrucción if?

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

Jonathan Keith mencionó esto. Controls.Clear() que puede funcionar, pero dependiendo del contexto (de "esto"), podría borrar otros controles también. Sin embargo, si el contexto lo permite, la respuesta de Jonathan puede tomar un par de ciclos de reloj. – hackerhasid

3

Esto eliminará todos los controles PictureBox desde el contenedor en particular (i asumir un gráfico en su caso).

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

       control.Dispose(); 
      } 
0

Parece que Hans Passant olvidó también un detalle muy importante (o tal vez solo estaba agregando las respuestas existentes, sin enviar una respuesta completa). En cualquier caso, esto es lo que tenía que hacer las dos cosas a invisiblize y disponer mis controles dinámicos:

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

¿Cuál fue el detalle muy importante que olvidó? –

Cuestiones relacionadas