【问题标题】:loop over all textboxes in a form, including those inside a groupbox循环遍历表单中的所有文本框,包括组框内的文本框
【发布时间】:2011-06-08 02:52:33
【问题描述】:

我在 winform 中有几个文本框,其中一些在 groupbox 内。我试图遍历表单中的所有文本框:

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 循环遍历表单中的所有文本框(包括组框内的文本框)?或者有什么更好/更优雅的方法?

【问题讨论】:

标签: vb.net winforms


【解决方案1】:

如果您不关心控件的顺序(而且我无法想象您应该这样做的原因),您可以按以下方式迭代地执行此操作(它非常简单,所以我认为不需要解释是必要的)。应该比任何递归都更有效率,尤其是当您有许多嵌套控件时,尽管我怀疑性能提升是否会很明显。

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

【讨论】:

    【解决方案2】:

    你可以使用这个函数,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
    

    【讨论】:

      【解决方案3】:

      您将需要使用递归。以下是使用扩展方法的 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”功能,也应该很容易去掉它。

      【讨论】:

        【解决方案4】:

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

        您最初会将您的表单(我)传递给子,它会遍历其中的控件以查找包含更多控件的控件。

        也可以看看这个问题:VB.NET - Iterating through controls in a container object

        【讨论】:

          猜你喜欢
          • 2011-06-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多