recorra todos los cuadros de texto en un formulario, incluidos los que están dentro de un grupo de cuadros

Tengo varios cuadros de texto en un formulario de win, algunos de ellos están dentro de un grupo de cuadros. Traté de recorrer todas las cajas de texto en mi forma:

For Each c As Control In Me.Controls If c.GetType Is GetType(TextBox) Then ' Do something End If Next 

Pero parecía omitir los que estaban dentro de la agrupación y hacer un círculo solo sobre las otras cajas de texto de la forma. Así que agregué otro bucle For Each para los cuadros de texto del cuadro de grupo:

 For Each c As Control In GroupBox1.Controls If c.GetType Is GetType(TextBox) Then ' Do something End If Next 

Me pregunto: ¿hay alguna manera de recorrer todas las cajas de texto en una forma, incluidas las que están dentro de una caja de grupo, con un único bucle For Each? ¿O una forma mejor / más elegante de hacerlo?

Gracias por adelantado.

Puedes usar esta función, linq podría ser una forma más elegante.

 Dim allTxt As New List(Of Control) For Each txt As TextBox In FindControlRecursive(allTxt, Me, GetType(TextBox)) '....' Next Public Shared Function FindControlRecursive(ByVal list As List(Of Control), ByVal parent As Control, ByVal ctrlType As System.Type) As List(Of Control) If parent Is Nothing Then Return list If parent.GetType Is ctrlType Then list.Add(parent) End If For Each child As Control In parent.Controls FindControlRecursive(list, child, ctrlType) Next Return list End Function 

Te gustaría hacer recursiones , por ejemplo (pseudocódigo, ya que no sé VB):

 Sub LoopControls (Control Container) if (Container has Controls) LoopControls(Container) For Each c As Control In Container if (Control is TextBox) // do stuff End Sub 

Pasaría su formulario (yo) al submarino inicialmente, y atravesaría los controles en él buscando los que contienen más controles.

También vea esta pregunta: VB.NET – Iteración a través de controles en un objeto contenedor

Tendrá que usar recursión. La siguiente es una solución de C # que usa un método de extensión y va un poco más allá del scope de su pregunta, pero la saqué de nuestro marco.

 static partial class ControlExtensions { public static void ApplyToMatchingChild(this Control parent, Action actionToApplyWhenFound, bool keepApplyingForever, params Func[] matchingChildCriteria) { ControlEventHandler reapplyEventHandler = null; if (keepApplyingForever) { reapplyEventHandler = (s, e) => { ApplyToMatchingChild(e.Control, actionToApplyWhenFound, keepApplyingForever, matchingChildCriteria); }; } SearchForMatchingChildTypes(parent, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria); } private static void SearchForMatchingChildTypes(Control control, Action actionToApplyWhenFound, ControlEventHandler reapplyEventHandler, params Func[] matchingChildCriteria) { if (matchingChildCriteria.Any(criteria => criteria(control))) { actionToApplyWhenFound(control); } if (reapplyEventHandler != null) { control.ControlAdded += reapplyEventHandler; } if (control.HasChildren) { foreach (var ctl in control.Controls.Cast()) { SearchForMatchingChildTypes(ctl, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria); } } } } 

Y para llamar:

 myControl.ApplyToMatchingChild(c => { /* Do Stuff to c */ return; }, false, c => c is TextBox); 

Eso aplicará una función a todos los cuadros de texto secundarios. Puede usar el parámetro keepApplyingForever para asegurarse de que su función se aplicará cuando se agreguen controles secundarios posteriormente. La función también le permitirá especificar cualquier número de criterios coincidentes, por ejemplo, si el control también es una etiqueta o algún otro criterio.

De hecho, utilizamos esto como una forma ordenada de llamar a nuestro contenedor de dependency injection para cada UserControl agregado a nuestro formulario.

Estoy seguro de que no debería tener demasiados problemas para convertirlo a VB.NET también … Además, si no desea la funcionalidad “keepApplyingForever”, también debería ser bastante fácil eliminarla.

Si no le importa el orden (y no puedo imaginar la razón por la que debería hacerlo) de los controles, puede hacerlo iterativamente de la siguiente manera (es bastante sencillo, así que no creo que sea necesaria ninguna explicación). ) Debería ser mucho más eficiente que cualquier recursión, especialmente si tiene muchos controles nesteds, aunque dudo que la ganancia de rendimiento sea aparente.

 Public Function FindAllControlsIterative(ByRef parent As Control) As List(Of TextBox) Dim list As New List(Of TextBox) Dim ContainerStack As New Stack(Of Control) ContainerStack.Push(parent) While ContainerStack.Count > 0 For Each child As Control In ContainerStack.Pop().Controls If child.HasChildren Then ContainerStack.Push(child) If child.GetType Is GetType(TextBox) Then list.Add(child) Next End While Return list End Function