2010-04-29 12 views
6

Tengo un Form llamado A.¿Cómo obtengo todos los controles de un formulario en Windows Forms?

A contiene muchos controles diferentes, incluido un GroupBox principal. Este GroupBox contiene muchas tablas y otras GroupBox es. Quiero encontrar un control que tenga, p. tab index 9 en el formulario A, pero no sé cuál GroupBox contiene este control.

¿Cómo puedo hacer esto?

+0

me gustaría usar el método de extensión de Map de Marc para este tipo de recursión: http://stackoverflow.com/questions/141467/recursive-list-flattening/229442#229442 – Oliver

Respuesta

4

Realice una búsqueda recursiva a través de la colección Controls de su formulario.

void FindAndSayHi(Control control) 
{ 
    foreach (Control c in control.Controls) 
    { 
     Find(c.Controls); 
     if (c.TabIndex == 9) 
     { 
      MessageBox.Show("Hi"); 
     } 
    } 
} 
1
void iterateControls(Control ctrl) 
{ 
    foreach(Control c in ctrl.Controls) 
    { 
     iterateControls(c); 
    } 
} 
2

Usted puede hacer un método como este:

public static Control GetControl(Control.ControlCollection controlCollection, Predicate<Control> match) 
{ 
    foreach (Control control in controlCollection) 
    { 
     if (match(control)) 
     { 
      return control; 
     } 

     if (control.Controls.Count > 0) 
     { 
      Control result = GetControl(control.Controls, match); 
      if (result != null) 
      { 
       return result; 
      } 
     } 
    } 

    return null; 
} 

... que se utiliza como esto:

Control control = GetControl(this.Controls, ctl => ctl.TabIndex == 9); 

Nota sin embargo, que TabIndex es un caso complicado, ya que comienza en 0 dentro de cada contenedor, por lo que puede haber varios controles en la misma forma teniendo el mismo TabIndex valor.

De cualquier manera, el método anterior se puede utilizar para el control de prácticamente cualquier propiedad de los controles:

Control control = GetControl(this.Controls, ctl => ctl.Text == "Some text"); 
13

Con recursividad ...

public static IEnumerable<T> Descendants<T>(this Control control) where T : class 
{ 
    foreach (Control child in control.Controls) { 

     T childOfT = child as T; 
     if (childOfT != null) { 
      yield return (T)childOfT; 
     } 

     if (child.HasChildren) { 
      foreach (T descendant in Descendants<T>(child)) { 
       yield return descendant; 
      } 
     } 
    } 
} 

Puede utilizar la función anterior como:

var checkBox = (from c in myForm.Descendants<CheckBox>() 
       where c.TabIndex == 9 
       select c).FirstOrDefault(); 

Eso obtendrá el primer CheckBox en cualquier lugar dentro del formulario que tiene un TabInde x de 9. Obviamente puede usar cualquier criterio que desee.

Si usted no es un fan de LINQ sintaxis de la consulta, lo anterior se puede volver a escribir como:

var checkBox = myForm.Descendants<CheckBox>() 
        .FirstOrDefault(x=>x.TabIndex==9); 
+0

Wow, eso es un extremo, forma demasiado complicada de encontrar un control con un índice de 9 en la pestaña. Felicitaciones por el esfuerzo. –

+2

Su método solo encuentra un control con un índice de tabulación de 9. El mío es un método de extensión que habilita efectivamente LINQ a WinForms. Es el mismo enfoque utilizado por LINQ a XML. Y no es complicado, es una recursión simple como muchas de las otras respuestas. La única diferencia es que estoy filtrando en el tipo que hace que el predicado sea más fácil de escribir. – Josh

+0

Ok, puedo agregar un parámetro int y ahora lo hace.En serio, nunca necesitarás nada de eso, solo necesitas encontrar un control con un índice de pestañas igual a n, y la gente tiene que mirarlo por lo menos durante unos segundos para averiguar qué hace. Además, preferiría escribir Find (this, 9) en lugar de una consulta, pero no quise ser grosero, este es un lugar para divertirse con el código después de todo. –

0

odio recursividad, así que siempre utilice una pila para este tipo de cosas. Esto asigna un controlador de eventos comunes a la CheckedChanged caso de todos los controles RadioButton en la jerarquía de control de corriente:

Stack<Control> controlStack = new Stack<Control>(); 
foreach (Control c in this.Controls) 
{ 
    controlStack.Push(c); 
} 
Control ctl; 
while (controlStack.Count > 0 && (ctl = controlStack.Pop()) != null) 
{ 
    if (ctl is RadioButton) 
    { 
     (ctl as RadioButton).CheckedChanged += new EventHandler(rb_CheckedChanged); 
    } 
    foreach (Control child in ctl.Controls) 
    { 
     controlStack.Push(child); 
    } 
} 

Desde aquí se puede adaptar el método de extensión de Josh Einstein para trabajar de esta manera.

Cuestiones relacionadas