Vb.net 循环遍历表单上的每个控件(包括容器中的控件),并用设置值替换文本占位符

Vb.net 循环遍历表单上的每个控件(包括容器中的控件),并用设置值替换文本占位符,vb.net,visual-studio-2013,controls,Vb.net,Visual Studio 2013,Controls,在我的项目中,我有一个名为DriveLetter的设置,我希望将此设置的值插入表单上多个控件的文本中(替换占位符) 我认为最简单的方法是循环表单上的每个控件并搜索占位符,但通过反复试验,我发现我无法做到这一点(至少以我尝试的方式),因为我使用了容器,例如SplitContainer和面板 下面是我到目前为止所拥有的,它考虑到了前面提到的SplitContainer和Panelcontainesr,但是我如何修改它,以便在不必显式检查当前控件是否为容器类型的情况下循环表单上的每个控件 Privat

在我的项目中,我有一个名为DriveLetter的设置,我希望将此设置的值插入表单上多个控件的文本中(替换占位符)

我认为最简单的方法是循环表单上的每个控件并搜索占位符,但通过反复试验,我发现我无法做到这一点(至少以我尝试的方式),因为我使用了容器,例如
SplitContainer
面板

下面是我到目前为止所拥有的,它考虑到了前面提到的
SplitContainer
Panel
containesr,但是我如何修改它,以便在不必显式检查当前控件是否为容器类型的情况下循环表单上的每个控件

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
Private DRIVE\u LETTER As String=My.Settings.DriveLetter
'**
'处理表单加载
''
私有子表单_Load(ByVal sender作为对象,ByVal e作为System.EventArgs)处理MyBase.Load
一封信(我)
端接头
'**
'更新文本placehoder的值
''
专用子替换DriveLetter(ByVal ctrlContainer作为控件)
对于ctrlContainer.Controls中的每个ctrl As控件
如果TypeOf ctrl为SplitContainer或TypeOf ctrl为Panel,则
替换驱动器号(ctrl)
其他的
ctrl.Text=Replace(ctrl.Text,“,UCase(驱动器号))
如果结束
下一个ctrl键
端接头

这应该可以做到,不过很明显,这里的文本将替换为DriveLetter(如果您愿意,我可以提供帮助)


这应该可以做到,尽管这里的文本显然要替换为DriveLetter(如果您愿意,我可以提供帮助)

还可以使用检查控件是否包含一个或多个子控件

如MSDN上所述,如果
控件
集合的
计数
大于零,则
HasChildren
属性将返回true。如果控件没有子控件,则访问
haschilds
属性不会强制创建
控件。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
Private Sub ReplaceDriveLetter(ByVal ctrlContainer作为控件)
对于ctrlContainer.Controls中的每个ctrl As控件
如果ctrl.HasChildren,则
替换驱动器号(ctrl)
其他的
ctrl.Text=Replace(ctrl.Text,“,UCase(驱动器号))
如果结束
下一个ctrl键
端接头
您还可以使用检查控件是否包含一个或多个子控件

如MSDN上所述,如果
控件
集合的
计数
大于零,则
HasChildren
属性将返回true。如果控件没有子控件,则访问
haschilds
属性不会强制创建
控件。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
Private Sub ReplaceDriveLetter(ByVal ctrlContainer作为控件)
对于ctrlContainer.Controls中的每个ctrl As控件
如果ctrl.HasChildren,则
替换驱动器号(ctrl)
其他的
ctrl.Text=Replace(ctrl.Text,“,UCase(驱动器号))
如果结束
下一个ctrl键
端接头

我建议使用堆栈,如果当前控件包含控件,则将所有这些控件添加到堆栈中,如果不包含控件,则将其弹出。我可以写一个答案,我只需要几分钟。我建议使用堆栈,然后如果当前控件包含控件,则将所有这些控件添加到堆栈中,如果不包含控件,则将其弹出。我可以写一个答案,我只需要几分钟。谢谢发帖。我可以添加驱动器号,但您的代码在“While(stackOfControls.Peek不是空的)”行生成错误,-InvalidOperationException未处理。@DavidGard抱歉,这对我很有效,但我认为这更好(请参见编辑)。我更改了它以确保堆栈不是空的。我通过包含行
If(currControl.Controls不是空的,也包括currControl.Controls.Count>0),然后
,而不是像我的示例中那样检查
控件的类型,从而使我的原始解决方案起作用。所以不是完整的代码,而是包含密钥的代码。谢谢你的帮助。@DavidGard好极了,好的。我很高兴你的代码工作正常,也很高兴我能帮上忙。谢谢你的发帖。我可以添加驱动器号,但您的代码在“While(stackOfControls.Peek不是空的)”行生成错误,-InvalidOperationException未处理。@DavidGard抱歉,这对我很有效,但我认为这更好(请参见编辑)。我更改了它以确保堆栈不是空的。我通过包含行
If(currControl.Controls不是空的,也包括currControl.Controls.Count>0),然后
,而不是像我的示例中那样检查
控件的类型,从而使我的原始解决方案起作用。所以不是完整的代码,而是包含密钥的代码。谢谢你的帮助。@DavidGard好极了,好的。我很高兴您的代码能够正常工作,也很高兴我能提供帮助。很抱歉,如果我用我在:;)中的示例让您走错了路哦,
HasChildern
=我的新好朋友!谢谢你指出,下一杯啤酒我请客;)对不起,如果我用我在:;)中的例子让你走错了路哦,
HasChildern
=我的新好朋友!谢谢你指出,下一杯啤酒我请客;)