在我的项目中,我有一个名为 DriveLetter 的设置,我希望将此设置的值插入到窗体上多个控件的文本中(替换占位符)。
我认为最简单的方法是遍历窗体上的每个控件并搜索占位符,但是通过反复试验,我发现我无法做到这一点(至少以我尝试的方式),因为我使用了容器,例如SplitContainer
和Panel
。
以下是我到目前为止所拥有的,它考虑了上述SplitContainer
和Panel
包含,但是我如何修改它以循环遍历窗体上的每个控件,而不必显式检查当前控件是否是一种容器?
Private DRIVE_LETTER As String = My.Settings.DriveLetter
'**
' Handle form loading
''
Private Sub form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReplaceDriveLetter(Me)
End Sub
'**
' Update the value of the <DRIVE_LETTER> text placehoder
''
Private Sub ReplaceDriveLetter(ByVal ctrlContainer As Control)
For Each ctrl As Control In ctrlContainer.Controls
If TypeOf ctrl Is SplitContainer Or TypeOf ctrl Is Panel Then
ReplaceDriveLetter(ctrl)
Else
ctrl.Text = Replace(ctrl.Text, "<DRIVE_LETTER>", UCase(DRIVE_LETTER))
End If
Next ctrl
End Sub
还可以使用 Control.HasChildren 属性来检查控件是否包含一个或多个子控件。
如 MSDN 所述,如果Controls
集合的Count
大于零,则 HasChildren
属性将返回 true。如果控件没有子项,则访问 HasChildren
属性不会强制创建Control.ControlCollection
,因此在遍历控件树时,引用此属性可以提供性能优势。
因此,您可以在以下位置更改函数:
Private Sub ReplaceDriveLetter(ByVal ctrlContainer As Control)
For Each ctrl As Control In ctrlContainer.Controls
If ctrl.HasChildren Then
ReplaceDriveLetter(ctrl)
Else
ctrl.Text = Replace(ctrl.Text, "<DRIVE_LETTER>", UCase(DRIVE_LETTER))
End If
Next ctrl
End Sub
这应该可以做到,尽管显然用 DriveLetter 替换了这里的文本(如果您愿意,我可以提供帮助)。
Private Sub ReplaceAllControlsOnForm()
Dim stackOfControls As New Stack(Of Control)
'add initial controls (all on form)
For Each c As Control In Me.Controls
stackOfControls.Push(c)
Next
'go until no controls are left
While (stackOfControls.Count > 0)
Dim currControl As Control = stackOfControls.Pop
currControl.Text = "text here"
'see if our control can contain controls
If (currControl.Controls IsNot Nothing AndAlso currControl.Controls.Count > 0) Then
'add all of these controls onto our stack
For Each c As Control In currControl.Controls
stackOfControls.Push(c)
Next
End If
End While
End Sub