枚举窗体中的所有控件(冗余)

Enumerate all controls in a form (redundant)

我正在尝试枚举满足特定条件的表单中的所有控件,如下面的代码

Public Enum MethodSeachEnum
    StartsWith = 1
    EndsWith = 2
    Contains = 3
End Enum

Public Function GetAllControls(Control As Control, Key As String, MethodSeach As MethodSeachEnum, ControlType As Type, Optional UseTag As Boolean = True) As IEnumerable(Of Control)
    Dim controls = Control.Controls.Cast(Of Control)()

    Return (controls.SelectMany(Function(ctrl) GetAllControls(ctrl, Metodo)).Concat(controls).Where(Function(c)
            Select Case MethodSeach
                Case MetodoSeachEnum.EndsWith
                    If (UseTag) Then
                        Return c.Tag.ToString.ToUpper.EndsWith(Key.ToUpper) And c.GetType() Is ControlType 
                    Else
                        Return c.Name.ToUpper.EndsWith(Key.ToUpper) And c.GetType() Is ControlType 
                    End If
                Case MetodoSeachEnum.StartsWith
                    If (UseTag) Then
                        Return c.Tag.ToString.ToUpper.StartsWith(Key.ToUpper) And c.GetType() Is ControlType 
                    Else
                        Return c.Name.ToUpper.StartsWith(Key.ToUpper) And c.GetType() Is ControlType 
                    End If
                Case MetodoSeachEnum.Contains
                    If (UseTag) Then
                        Return c.Tag.ToString.ToUpper.Contains(Key.ToUpper) And c.GetType() Is ControlType 
                    Else
                        Return c.Name.ToUpper.Contains(Key.ToUpper) And c.GetType() Is ControlType 
                    End If
                Case Else
                    Return False
            End Select
        End Function))
End Function

在我的表单中有一个 GroupBox 和一些 TextBox。这些 TextBox 没有返回,我不明白为什么...

这里是我调用这个函数的方式

Dim ctrls = GetAllControls(FormTagliente, "txtQuote", MetodoSeachEnum.StartsWith, GetType(TextBox), False)

        For Each txt As TextBox In ctrls 

            ...

        Next

恕我直言,信息太少无法回答您的问题"why that doesn't work for your specific case"
此外,您的代码中缺少带有两个参数的 GetAllControls,也许问题出在这里
无论如何,我对您的代码进行了一些尝试(但尚未对其进行测试,因此它更像是一个 POC),这就是我得到的:

Enum SearchMethod
    StartsWith = 1
    EndsWith = 2
    Contains = 3
End Enum

Function GetAllControls(Of T As Control)(ctrl As Control, key As String, method As SearchMethod, Optional useTag As Boolean = True) As IEnumerable(Of T)
    ' TODO validate args
    Dim upperKey = key.ToUpper

    Dim searchPredicates() As Func(Of String, Boolean) = {
        Function(src, tgt) src.StartsWith(upperKey),
        Function(src, tgt) src.EndsWith(upperKey),
        Function(src, tgt) src.Contains(upperKey)
    }
    Dim ctrlSelector As Func(Of Control, String) = If(useTag, Function(c) c.Tag.ToString.ToUpper, Function(c) c.Name.ToUpper)

    Return GetAllControlsIterator(Of T)(ctrl, ctrlSelector, searchPredicates(CInt(method) - 1))
End Function

Private Iterator Function GetAllControlsIterator(Of T As Control)(ctrl As Control, ctrlSelector As Func(Of Control, String), searchPredicate As Func(Of String, Boolean)) As IEnumerable(Of T)
    For Each child In ctrl.Controls
        If searchPredicate(ctrlSelector(child)) AndAlso TypeOf child Is T Then Yield DirectCast(child, T)

        For Each grandChild In GetAllControlsIterator(Of T)(child, ctrlSelector, searchPredicate)
            Yield DirectCast(grandChild, T)
        Next
    Next
End Function

这个想法是将 "construct the criteria logic" 与实际的 "loop, search, yield" 分开,使用通用约束强制 targetType 成为控件(并直接将 "good" return类型)。我还发现使用 Iterator 块更简单,但更个性化
也许这可以帮助您解决问题?