Obtener todos los controles de un tipo específico

Tengo múltiples pictureboxes y necesito cargar imágenes aleatorias en ellos durante el tiempo de ejecución. Así que pensé que sería bueno tener una colección de todos los pictureboxes y luego asignarles imágenes usando un simple loop. Pero, ¿cómo debería hacerlo? ¿O tal vez hay otras soluciones mejores para tal problema?

Usando un poco de LINQ:

foreach(var pb in this.Controls.OfType()) { //do stuff } 

Sin embargo, esto solo se ocupará de PictureBoxes en el contenedor principal.

Puedes usar este método:

 public static IEnumerable GetControlsOfType(Control root) where T : Control { var t = root as T; if (t != null) yield return t; var container = root as ContainerControl; if (container != null) foreach (Control c in container.Controls) foreach (var i in GetControlsOfType(c)) yield return i; } 

Entonces podrías hacer algo como esto:

 foreach (var pictureBox in GetControlsOfType(theForm)) { // ... } 

Si al menos está en .NET 3.5, entonces tiene LINQ, lo que significa que desde que ControlCollection implementa IEnumerable puede hacer lo siguiente:

 var pictureBoxes = Controls.OfType(); 

Aquí hay otra versión, ya que las existentes no eran exactamente lo que tenía en mente. Éste funciona como un método de extensión, opcionalmente, y excluye la comprobación del tipo de contenedor principal / raíz. Este método es básicamente un método “Obtener todos los controles descendientes del tipo T”:

 public static System.Collections.Generic.IEnumerable ControlsOfType(this System.Web.UI.Control control) where T: System.Web.UI.Control{ foreach(System.Web.UI.Control childControl in control.Controls){ if(childControl is T) yield return (T)childControl; foreach(var furtherDescendantControl in childControl.ControlsOfType()) yield return furtherDescendantControl; } } 

Una función simple, fácil de entender, recursiva, y funciona llamándola dentro de cualquier control de formulario:

 private void findControlsOfType(Type type, Control.ControlCollection formControls, ref List controls) { foreach (Control control in formControls) { if (control.GetType() == type) controls.Add(control); if (control.Controls.Count > 0) findControlsOfType(type, control.Controls, ref controls); } } 

Puedes llamarlo de múltiples maneras. Para obtener los botones:

 List buttons = new List(); findControlsOfType(typeof(Button), this.Controls, ref buttons); 

Para obtener los paneles:

 List panels = new List(); findControlsOfType(typeof(Panel), this.Controls, ref panels); 

etc.

Yo uso este método genérico recursivo:

La suposición de este método es que si el control es T, entonces el método no se ve en sus elementos secundarios. Si también necesita mirar a sus hijos, puede cambiarlo fácilmente en consecuencia.

 public static IList GetAllControlsRecusrvive(Control control) where T :Control { var rtn = new List(); foreach (Control item in control.Controls) { var ctr = item as T; if (ctr!=null) { rtn.Add(ctr); } else { rtn.AddRange(GetAllControlsRecusrvive(item)); } } return rtn; } 
  public static List FindControlByType(Control mainControl,bool getAllChild = false) where T :Control { List lt = new List(); for (int i = 0; i < mainControl.Controls.Count; i++) { if (mainControl.Controls[i] is T) lt.Add((T)mainControl.Controls[i]); if (getAllChild) lt.AddRange(FindControlByType(mainControl.Controls[i], getAllChild)); } return lt; } 

Esto para mí es de lejos el más fácil. En mi aplicación, estaba tratando de borrar todos los cuadros de texto en un panel:

  foreach (Control c in panel.Controls) { if (c.GetType().Name == "TextBox") { c.Text = ""; } }