65.9K
CodeProject 正在变化。 阅读更多。
Home

世界上最简单的多选 TreeView

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.80/5 (6投票s)

2009年5月24日

CPOL

3分钟阅读

viewsIcon

47459

一种快速简便的方法,可以在TreeView中启用多选,并轻松迭代选定的节点。

引言

你可能会认为,允许用户在TreeView中选择多个项目(就像在ComboBox中一样),然后浏览选定项目的集合应该很简单,但事实并非如此。Microsoft没有提供一种简单的方法来做到这一点。本文将向您展示一种简单的方法来实现多选,以及一种简单的方法来维护选定节点的集合——无需派生新的控件,也无需使用递归。

背景

Microsoft的TreeView控件允许你在每个节点旁边显示一个复选框。但是,这些复选框有点难看,而且它们位于每个节点旁边,这可能不是你想要的。

我知道我可以使用ImageList并替换我自己的更优雅的复选框,但是TreeView控件会坚持为每个节点添加图像。如果我把一个空白图像放在ImageList的第一个位置,那么在没有复选框的节点旁边就会留下难看的空白。

同样糟糕的是,我找到的所有构建选定节点集合的解决方案都涉及使用递归。如果正确实现,递归非常有用。但是,它可能会造成混乱。

我希望获得比这些方法允许的更多控制,因此我决定稍微修改规则并实现一个非常简单的解决方案。与其显示难看的复选框,我决定只更改选定节点的背景颜色。与其使用递归,我认为第二个隐藏的TreeView可以保存我选定的节点集合。

使用代码

我的方法涉及捕获TreeViewAfterSelect事件。事实上,所有工作都在这里完成。代码出奇地简单。它假设你有两个TreeView,一个标记为Visible=False。因为它不可见,所以它可以是任何大小,并且可以放在任何位置。把它想象成你的隐藏记事本。

Private Sub TreeView1_AfterSelect(ByVal sender As System.Object,
                       _ByVal e As System.Windows.Forms.TreeViewEventArgs)
                       _Handles TreeView1.AfterSelect
    If TreeView1.SelectedNode.Level = 0 Then Exit Sub
    Dim newNode As New TreeNode
    newNode = TreeView1.SelectedNode.Clone
    With TreeView1.SelectedNode
        If .BackColor = Color.White Then
            .BackColor = Color.Yellow
            TreeView2.Nodes.Add(newNode)
        Else
            .BackColor = Color.White
            TreeView2.Nodes.RemoveByKey(.Name)
        End If
        TreeView1.SelectedNode = .Parent
    End With
End Sub

此子例程的第一行阻止用户选择根节点(级别0)。如果需要,可以添加此限制以处理TreeView的其他级别。例如,我用它来阻止除TreeView节点的最低级别(在我的例子中是级别3)以外的所有级别被选中,所以我的代码如下所示:

If TreeView1.SelectedNode.Level < 3 Then Exit Sub

你不能直接从一个TreeView复制节点到另一个TreeView,所以我克隆了SelectedNode。然后,我决定下一步该做什么。如果SelectedNodeBackColor为白色,我将其更改为黄色。这使得它看起来像荧光笔标记了一样。当然,你可以选择任何你想要的颜色。在我将其更改为黄色之后,我将克隆的节点(SelectedNode的完美副本)添加到第二个隐藏的TreeView中。如果SelectedNodeBackColor已经是黄色(意味着用户之前已选择它,但现在想要取消选择它),我将恢复其白色BackColor,然后从第二个TreeView中删除克隆的节点。

结果是,第二个隐藏的TreeView始终包含用户在第一个可见TreeView中选择的节点的集合。一旦用户单击“确定”,遍历这些选定节点就成了一件简单的事情。

Private Sub ShowIt(ByVal sender As System.Object, ByVal e As System.EventArgs)
                   _Handles btnOK.Click
    Dim aNode As TreeNode
    Dim msg As String = "Selected nodes:" & vbCrLf
    For Each aNode In TreeView2.Nodes
        msg = msg & aNode.Text & vbCrLf
    Next
    MsgBox(msg)
End Sub

关注点

所有这一切之所以有效,是因为每个节点必须具有唯一的名称。尝试使用Text属性会造成混乱,因为你无法保证两个节点不会具有相同的文本。

上面第一个子例程的最后一行很有趣。我发现,由于焦点仍然停留在SelectedNode上,因此BackColor的变化并不立即显而易见。因为我知道每个SelectedNode都会有一个父节点,所以我决定将焦点转移到父节点。

结论

正如我上面提到的,还有其他解决这些问题的方案,它们展示了一些重要的编程方法和创造性的想法。其中一个解决方案可能更适合您的需求。但是,我希望您发现我的简单方法是一个不错的替代方案。

© . All rights reserved.