枚举窗体中的所有控件(冗余)
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
块更简单,但更个性化
也许这可以帮助您解决问题?
我正在尝试枚举满足特定条件的表单中的所有控件,如下面的代码
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
块更简单,但更个性化
也许这可以帮助您解决问题?