Treeview 提升 drawnode 但一些更改不会传播到屏幕

Treeview raising drawnode but some changes won't propagate to the screen

我正在 VB 中使用树视图,并将 OwnerDrawText 作为我的绘制模式。我在我的树视图中处理了 Me.DrawNode 以允许我突出显示特定项目(即保持最后一个节点突出显示等等)。我看到正在调用 drawnode 并尝试将所有背景设置为自定义颜色购买这样做

Public Class Form1
    Private nodelist As New List(Of TreeNode)

    Public Sub New()
        InitializeComponent()
        TreeView1.Nodes.AddRange(New TreeNode() {
            New TreeNode("Text of Node 0") With {.Name = "Node0"},
            New TreeNode("Text of Node 1") With {.Name = "Node1"},
            New TreeNode("Text of Node 2") With {.Name = "Node2"},
            New TreeNode("Text of Node 3") With {.Name = "Node3"},
            New TreeNode("Text of Node 4") With {.Name = "Node4"}
        })
    End Sub

    Private Sub myTreeView_DrawNode(ByVal sender As Object, ByVal e As DrawTreeNodeEventArgs) Handles TreeView1.DrawNode
        Console.WriteLine(e.Node.Text & " Rewritten")

        ' Draw the background and node text for a selected node.
        If nodelist.Contains(e.Node) Then
            e.Graphics.FillRectangle(New SolidBrush(Color.Chartreuse), e.Bounds)
            TextRenderer.DrawText(e.Graphics, e.Node.Text, e.Node.NodeFont, e.Bounds,
                                  Color.Black, Color.Empty,
                                  TextFormatFlags.VerticalCenter)
        Else
            e.Graphics.FillRectangle(New SolidBrush(Color.Black), e.Bounds)
            TextRenderer.DrawText(e.Graphics, e.Node.Text, e.Node.NodeFont, e.Bounds,
                                  Color.White, Color.Empty,
                                  TextFormatFlags.VerticalCenter)
        End If
    End Sub

    Private Sub myTreeView_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles TreeView1.MouseDown
        Console.WriteLine("Clicked")
        Dim clickedNode As TreeNode = TreeView1.GetNodeAt(e.X, e.Y)
        nodelist.Add(clickedNode)
        If nodelist.Count > 3 Then
            nodelist.RemoveAt(0)
        End If
        TreeView1.SelectedNode = clickedNode
    End Sub
End Class

此代码应该突出显示最后三个 selected 节点。但是,如果单击所有节点,从 0 到 5,您将看到它突出显示所有内容。然后如果你 select 节点 2 你会看到所有节点都被重绘(Console.WriteLine 显示这个),我认为这意味着节点 1 和 2 应该失去高亮颜色,但他们没有.

绘图部分是正确的,即使它可以简化:相同的方法可以用于背景和文本渲染,DRY 代码。

MouseDown事件中的逻辑需要部分重构,所以选中和未选中的Node实际上是在Node集合中添加和移除,nodelist 字段.

TreeView 也需要通知 变化,调用它的 Invalidate() 方法,所以 Control 可以重新绘制新选择的节点(Invalidate() 导致控件重新绘制自身,引发其 Paint 或类似的相关事件:在本例中为 DrawNode 事件)。

简化绘图方法:

► 注意:在这里,我使用 e.Node.Bounds 作为节点背景和文本的边界矩形。 e.Bounds 可以代替,如果矩形在实际实现中看起来 太紧。有待测试(这种情况下可以考虑优先考虑)

Private Sub TreeView1_DrawNode(sender As Object, e As DrawTreeNodeEventArgs) Handles TreeView1.DrawNode
    Console.WriteLine(e.Node.Text & " Rewritten")

    Dim backColor As Color = Color.Black
    Dim foreColor As Color = Color.White
    If nodelist.Contains(e.Node) Then
        backColor = Color.Chartreuse
        foreColor = Color.Black
    End If

    e.Graphics.FillRectangle(New SolidBrush(backColor), e.Node.Bounds)
    TextRenderer.DrawText(e.Graphics, e.Node.Text, e.Node.NodeFont, e.Node.Bounds,
                          foreColor, Color.Transparent, TextFormatFlags.VerticalCenter)
End Sub

MouseDown 事件将当前选定的节点添加到 nodelist 集合(如果它不存在),否则从集合中删除该节点。
在将所选节点添加到集合之前还要验证另一个条件:集合不能包含超过 4 个项目;如果集合已经已满,则不会添加所选节点。

Private Sub myTreeView_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles TreeView1.MouseDown
    Dim clickedNode As TreeNode = TreeView1.GetNodeAt(e.X, e.Y)
    If nodelist.Contains(clickedNode) Then
        nodelist.Remove(clickedNode)
    Else
        If nodelist.Count < 4 Then
            nodelist.Add(clickedNode)
            TreeView1.SelectedNode = clickedNode
        End If
    End If
    TreeView1.Invalidate()
End Sub