循环遍历表单中的所有文本框,包括组框内的文本框

时间:2011-01-12 20:55:11

标签: vb.net winforms

我在winform中有几个文本框,其中一些文本框位于一个组框内。我试图在表单中循环遍历所有文本框:

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

但是它似乎跳过了groupbox中的那些并且只在表单的其他文本框中循环。所以我为groupbox文本框添加了另一个For Each循环:

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

我想知道:有没有办法循环覆盖表单中的所有文本框 - 包括组框内的文本框 - 只有一个For Each循环?或者是更好/更优雅的方式吗?

提前致谢。

4 个答案:

答案 0 :(得分:18)

您可以使用此功能,linq可能是更优雅的方式。

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

答案 1 :(得分:1)

你想要做递归,例如(伪代码,因为我不知道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

你最初会将你的表单(我)传递给sub,它将遍历其中的控件,寻找包含更多控件的控件。

另请查看此问题:VB.NET - Iterating through controls in a container object

答案 2 :(得分:0)

您需要使用递归。以下是使用扩展方法的C#解决方案,并且稍微超出了您的问题的范围,但我只是从我们的框架中提取它。

static partial class ControlExtensions
{
    public static void ApplyToMatchingChild(this Control parent, Action<Control> actionToApplyWhenFound, bool keepApplyingForever, params Func<Control, bool>[] 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<Control> actionToApplyWhenFound, ControlEventHandler reapplyEventHandler, params Func<Control, bool>[] 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<Control>())
            {
                SearchForMatchingChildTypes(ctl, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria);
            }
        }
    }
}

致电:

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

这会将函数应用于所有子文本框。您可以使用keepApplyingForever参数确保稍后添加子控件时将应用您的函数。该功能还允许您指定任意数量的匹配条件,例如,如果控件也是标签或其他标准。

我们实际上使用它作为一种简洁的方法来为我们的表单中添加的每个UserControl调用我们的依赖注入容器。

我确信你不应该有太多问题converting it to VB.NET ...另外,如果你不想要“keepApplyingForever”功能,那么它也应该很容易去除它。

答案 3 :(得分:0)

如果你不关心控件的顺序(我无法想象你应该这么做的话),你可以用以下方式迭代地完成这个(它很简单,所以我不喜欢#39;认为任何解释都是必要的)。应该比任何递归更有效,特别是如果你有很多嵌套控件,但我怀疑性能增益是否明显。

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