【问题标题】:Dynamic Treeview Height动态树视图高度
【发布时间】:2013-04-25 14:11:10
【问题描述】:

当我加载它时,我的树视图已折叠,因此它大约为 100x150 像素大。当它展开时,我希望树视图显示所有展开的节点。

为了做到这一点,表单需要随着树视图变大而变大,对吧?我是 VB.net 的新手,我试图在树视图中找到“GrowOnly”属性,但我找不到……有人做过吗?

【问题讨论】:

    标签: vb.net winforms dynamic treeview height


    【解决方案1】:

    以下扩展函数可以解决高度和宽度的问题。树视图本身永远不会被传入,只有节点的集合。请参阅下面的示例调用。

    ''' <summary>
    ''' Measures the total height and width of all expanded tree nodes
    ''' </summary>
    ''' <param name="nodes">TreeNodeCollection which should be measured</param>
    ''' <returns>
    '''     Size structure representing the height and width of a rectangle formed from
    '''     the top-left of the first node in the collection, the right boundary of the
    '''     right-most expanded node, and the bottom boundary of the bottom-most
    '''     expanded node.
    ''' </returns>
    <System.Runtime.CompilerServices.Extension()>
    Public Function MeasureExpansion(nodes As TreeNodeCollection) As Size
    
        Dim size As New Size(0, 0)
    
        For Each node As TreeNode In nodes
    
            size.Height += node.Bounds.Height
    
            Dim newWidth As Integer = node.Bounds.Right
    
            If newWidth > size.Width Then
                size.Width = newWidth
            End If
    
            If node.IsExpanded Then
    
                Dim subNodeSize As Size = node.Nodes.MeasureExpansion()
    
                If subNodeSize.Width > size.Width Then
                    size.Width = subNodeSize.Width
                End If
    
                size.Height += subNodeSize.Height
    
            End If
    
        Next
    
        Return size
    
    End Function
    

    下面的示例调用。请注意,示例树视图禁用了滚动条。如果允许滚动条,则可能需要填充结果大小。

    tvDefinitions.Nodes.Clear()
    
    <treeview loaded here>
    
    tvDefinitions.ExpandAll()
    
    tvDefinitions.Size = tvDefinitions.Nodes.MeasureExpansion()
    

    另请注意,当树视图中只有一个节点时,使用 AfterExpand/AfterCollapse 事件来触发树视图的大小调整不起作用。该事件不会触发。

    【讨论】:

      【解决方案2】:

      您可以捕获BeforeExpandAfterExpand TreeView 事件以检测用户何时更改节点区域的高度。在那个事件处理程序中,您需要找到最后一个节点的底部(使用Bounds 属性),然后您最终需要更改表单的高度。

      确保 TreeView 的 Anchor 属性包括顶部和底部,以便它随窗体一起增长。

      当然,表单必须比 TreeView 高。底部节点的 Bounds.Bottom 属性不会完全是树视图的底部,所以我下面的示例首先通过 TreeView 和表单之间的高度差来膨胀它,然后是通过 TreeView 的客户端高度和TreeView 的总高度。它在我的最后工作正常。

      您可以将相同的方法分配给BeforeExpandAfterExpand 事件。请注意,它通过遍历节点找到最后一个节点来找到最后一个节点;您需要检查以确保这可以保证为您提供最后一个节点。

      编辑:您需要在开始任何操作之前告诉树滚动以显示第一个节点,以便它始终如一地工作:因此EnsureVisible() 调用。

      Private Sub TreeView1_BeforeOrAfterExpand(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterExpand, TreeView1.AfterCollapse
          Dim lastNode As TreeNode = TreeView1.Nodes(0)
      
          TreeView1.Nodes(0).EnsureVisible()
      
          While lastNode.LastNode IsNot Nothing And lastNode.IsExpanded
              lastNode = lastNode.LastNode
          End While
      
          Dim diffBetweenFormAndTreeview As Integer = Me.Height - TreeView1.Height
          Dim diffBetweenTreeviewTotalAndClient As Integer = TreeView1.Height - TreeView1.ClientSize.Height
          Me.Height = lastNode.Bounds.Bottom + diffBetweenFormAndTreeview + diffBetweenTreeviewTotalAndClient
      End Sub
      

      【讨论】:

        【解决方案3】:

        处理 AfterExpand / AfterCollapse 事件

        添加事件处理程序 AfterExpand 和 AfterCollapse 以使树视图对节点的展开/折叠做出反应。我对这个例子的填充进行了硬编码,但本质上这只是用于调整表单大小的菜单、按钮等的高度。

        Private Sub Rapports_tvAllReports_AfterExpand(sender As Object, e As System.Windows.Forms.TreeViewEventArgs) Handles Rapports_tvAllReports.AfterExpand, Rapports_tvAllReports.AfterCollapse
            Dim Padding As Integer = 140 'Customize this, basically accounts for all buttons or menus included in the form which nests the treeview
            Dim TreeViewHeight As Integer = GetOpenedNodesRecursively(Rapports_tvAllReports)
        
            If formWindow = FormWindowState.Normal Then Me.Size = New Size(345, TreeViewHeight + Padding)
        End Sub
        

        我们所做的只是增加 Y 并将新的 Y 设置到表单中。为了使 treeview 与表单一起正确调整大小,请将其 锚定top 和 bottom

        递归遍历节点

        这个函数会遍历根节点,在打开的节点上调用递归函数。

        Private Function GetOpenedNodesRecursively(ByVal aTreeView As TreeView)
            Dim Y As Integer = 0
        
            'Go through each node of the treeview (first level)
            For Each n As TreeNode In aTreeView.Nodes
                Y += Rapports_tvAllReports.ItemHeight
        
                'If the user expands a node, recursively increment the Y
                If n.IsExpanded Then Y += RecursiveYIncrement(n)
            Next
        
            Return Y
        End Function
        

        现在只需使用递归函数不断增加 TreeViewHeight,该函数将返回在当前树视图中展开的所有节点的高度 (Y)。

        Private Function RecursiveYIncrement(ByVal n As TreeNode)
            Dim Y As Integer = 0
        
            'Go through each node of the treeview (first level)
            For Each aNode As TreeNode In n.Nodes
                Y += Rapports_tvAllReports.ItemHeight
        
                'If the user expands a node, recursively increment the Y
                If aNode.IsExpanded Then Y += RecursiveYIncrement(aNode)
            Next
        
            Return Y
        End Function
        

        视觉再现

        完成后的效果如下:

        我们从一个折叠的树视图开始

        然后我们可以扩展一些节点,表单会相应增长

        然后我们可以重新折叠节点并展开更多,表格再次调整!

        请原谅我在屏幕截图中的法语,这是魁北克的常态......我们有义务这样做!

        【讨论】:

          猜你喜欢
          • 2019-09-04
          • 2015-03-07
          • 2015-01-10
          • 2020-01-30
          • 1970-01-01
          • 1970-01-01
          • 2016-03-30
          • 2018-04-09
          • 1970-01-01
          相关资源
          最近更新 更多