You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历项目中所有控件(含未加载的WinForm、UserControl控件)

实现步骤

你已经完成了命名空间下类型的获取,接下来按以下逻辑处理即可:

  • 从获取到的类型中筛选出所有继承自Form、UserControl的控件容器类型
  • 对每个容器类型进行安全实例化,不需要调用Show方法,就能获取到设计阶段定义的所有控件(不会触发界面渲染和Load事件)
  • 递归遍历容器内的所有层级的子控件,同时收集需要的属性信息
  • 遍历完成后释放实例化的容器对象,避免内存泄漏
完整代码实现
' 你原有的获取命名空间下所有类型的方法
Private Function GetTypesInNamespace(ByVal assembly As Assembly, ByVal [nameSpace] As String) As Type()
    Return assembly.GetTypes().Where(Function(t) String.Equals(t.[Namespace], [nameSpace], StringComparison.Ordinal)).ToArray()
End Function

' 定义存储控件信息的结构
Public Structure ControlInfo
    Public ControlName As String
    Public TagValue As Object
    Public ParentName As String
    Public ContainerName As String ' 所属的窗体/用户控件名称
End Structure

' 递归遍历控件的方法
Private Sub TraverseControls(ByVal parentControl As Control, ByVal containerName As String, ByRef resultList As List(Of ControlInfo))
    For Each ctl As Control In parentControl.Controls
        ' 收集当前控件信息
        Dim info As New ControlInfo()
        info.ControlName = ctl.Name
        info.TagValue = ctl.Tag
        info.ParentName = parentControl.Name
        info.ContainerName = containerName
        resultList.Add(info)
        
        ' 如果当前控件是容器或用户控件,递归遍历子控件
        If ctl.HasChildren OrElse TypeOf ctl Is UserControl Then
            TraverseControls(ctl, containerName, resultList)
        End If
    Next
End Sub

' 主调用方法,获取所有控件信息
Public Function GetAllProjectControls() As List(Of ControlInfo)
    Dim result As New List(Of ControlInfo)()
    ' 获取当前程序集,如果你要遍历其他程序集自行修改
    Dim currentAssembly As Assembly = Assembly.GetExecutingAssembly()
    ' 替换为你自己的项目命名空间
    Dim allTypes As Type() = GetTypesInNamespace(currentAssembly, "你的项目命名空间")
    
    ' 筛选所有窗体和用户控件类型
    Dim containerTypes = allTypes.Where(Function(t) GetType(Form).IsAssignableFrom(t) OrElse GetType(UserControl).IsAssignableFrom(t)).ToList()
    
    For Each type In containerTypes
        ' 跳过抽象类、设计器生成的基类
        If type.IsAbstract Then Continue For
        Try
            ' 实例化容器,不需要Show
            Dim instance = Activator.CreateInstance(type)
            Dim container As Control = CType(instance, Control)
            ' 遍历当前容器的所有控件
            TraverseControls(container, type.Name, result)
            ' 释放资源
            container.Dispose()
        Catch ex As Exception
            ' 处理部分构造函数有参数无法实例化的情况,可自行添加日志
            Continue For
        End Try
    Next
    
    Return result
End Function
注意事项

如果你的控件是在窗体/用户控件的Load、Shown事件中动态生成的,直接实例化不会触发这些事件,无法获取到动态控件。如果需要覆盖这部分控件,可在实例化后手动调用OnLoad方法。
如果项目中存在自定义容器控件,可在筛选容器类型的逻辑里补充对应类型的判断规则。
如果部分窗体的构造函数需要传入参数,需要修改Activator.CreateInstance的调用逻辑,传入对应的构造参数避免实例化失败。

内容的提问来源于stack exchange,提问作者Adelina Andreea trandafir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 12:24:07