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

WPF自定义TreeViewPlus控件二级及以上节点无法展开求助

解决WPF自定义TreeViewItem二级及以上节点无法展开的问题

我仔细梳理了你的代码,找到了几个可能导致二级节点无法展开的核心问题,下面一步步帮你修复:

1. 错误的子目录判断逻辑

你的构造函数里判断是否存在子目录的代码是:

If Not dir.EnumerateDirectories Is Nothing Then

这是典型的逻辑错误——dir.EnumerateDirectories()返回的是一个永远不会为Null的IEnumerable(Of DirectoryInfo),哪怕目录下没有子文件夹,它也是一个空的枚举集合,而非Nothing。这会导致不管目录有没有子文件夹,都强制添加一个空的TreeViewPlus项,不仅影响UI体验,还可能掩盖真正的加载问题。

修复判断逻辑,改为检查是否存在实际的子目录:

If dir.EnumerateDirectories().Any() Then

2. 静默捕获异常,无法排查问题

你的代码里所有异常都被Catch ex As Exception捕获,但没有任何日志输出或提示。如果二级目录存在权限限制(比如系统保护目录),EnumerateDirectories()会抛出异常,导致子节点无法加载,但你完全不知道发生了什么。

建议在捕获异常时添加调试日志,方便定位问题:

Catch ex As Exception
    System.Diagnostics.Debug.WriteLine($"加载目录 {dir.FullName} 失败: {ex.Message}")
End Try

3. 确保Expanded事件可靠绑定

虽然VB.NET的Handles Me.Expanded理论上能绑定每个实例的事件,但动态创建控件时偶尔会出现事件绑定失效的情况。你可以手动绑定事件,替代Handles关键字,确保事件能稳定触发:

修改构造函数,添加手动事件绑定:

Public Sub New(dir As DirectoryInfo)
    Me.dir = dir
    ' 手动绑定Expanded事件
    AddHandler Me.Expanded, AddressOf TreeViewPlus_Expanded
    Try
        If dir.EnumerateDirectories().Any() Then
            Me.Items.Add(New TreeViewPlus)
        End If
    Catch ex As Exception
        System.Diagnostics.Debug.WriteLine($"初始化目录 {dir.FullName} 失败: {ex.Message}")
    End Try
End Sub

同时去掉事件方法的Handles Me.Expanded:

Private Sub TreeViewPlus_Expanded(sender As Object, e As RoutedEventArgs)
    ' ... 原有代码 ...
End Sub

4. 优化节点Header设置逻辑

你目前在根节点外部设置Header,在二级节点的Expanded事件里设置Header,可以统一放在构造函数里,让代码更简洁清晰:

Public Sub New(dir As DirectoryInfo)
    Me.dir = dir
    AddHandler Me.Expanded, AddressOf TreeViewPlus_Expanded
    ' 直接在构造函数中设置Header
    Me.Header = dir.Name
    Try
        If dir.EnumerateDirectories().Any() Then
            Me.Items.Add(New TreeViewPlus)
        End If
    Catch ex As Exception
        System.Diagnostics.Debug.WriteLine($"初始化目录 {dir.FullName} 失败: {ex.Message}")
    End Try
End Sub

这样初始化根节点时就不需要额外设置Header了:

For Each Drive As IO.DriveInfo In IO.DriveInfo.GetDrives
    Dim item As TreeViewPlus = New TreeViewPlus(Drive.RootDirectory)
    ' 移除这行冗余代码:item.Header = Drive.Name
    TRV_Arbre.Items.Add(item)
Next

完整修复后的TreeViewPlus代码

Private Class TreeViewPlus
    Inherits TreeViewItem
    Public dir As IO.DirectoryInfo

    Public Sub New()
    End Sub

    Public Sub New(dir As DirectoryInfo)
        Me.dir = dir
        AddHandler Me.Expanded, AddressOf TreeViewPlus_Expanded
        Me.Header = dir.Name
        Try
            ' 正确判断是否存在子目录
            If dir.EnumerateDirectories().Any() Then
                ' 添加空项显示展开箭头
                Me.Items.Add(New TreeViewPlus)
            End If
        Catch ex As Exception
            System.Diagnostics.Debug.WriteLine($"初始化目录 {dir.FullName} 失败: {ex.Message}")
        End Try
    End Sub

    Private Sub TreeViewPlus_Expanded(sender As Object, e As RoutedEventArgs)
        Me.Items.Clear()
        Try
            For Each folder In dir.EnumerateDirectories()
                Dim item As TreeViewPlus = New TreeViewPlus(folder)
                item.Name = Text.RegularExpressions.Regex.Replace(folder.FullName, "[^a-zA-Z0-9]", "")
                Me.Items.Add(item)
            Next
        Catch ex As Exception
            System.Diagnostics.Debug.WriteLine($"加载子目录 {dir.FullName} 失败: {ex.Message}")
        End Try
    End Sub
End Class

按照上面的修改,应该能解决二级及以上节点无法展开的问题。如果仍有异常,查看调试窗口的日志信息,就能快速定位具体原因了。

内容的提问来源于stack exchange,提问作者Benoit Bouckaert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:07:39