Dynamic Treeview Height
My treeview is collapsed when I load it so it's about 100x150 pixels big. When it is expanded, I want the treeview to show all of the expanded nodes.
In order to do that the form would need to get larger as the treeview gets larger, right? I'm new at VB.net and I was trying to find a "GrowOnly" property in the treeview but I couldn't find one... Has anyone ever done this?
Handle AfterExpand / AfterCollapse Events
Add the event handlers AfterExpand and AfterCollapse to make the treeview react to the expanding / collapsing of the nodes. I hardcoded the padding for this example, but essentially this is just the height of the menus, buttons, etc that will be used to resize the form.
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
All we do is increment the Y and set that new Y to the form. In order for the treeview to correctly resize along with the form, anchor it to the top and bottom.
Recursively go through nodes
This function will go through the root nodes and call a recursive function on the opened nodes.
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
Now just keep incrementing the TreeViewHeight using the recursive function that will return the height (Y) of all nodes that are expanded in the current tree view.
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
Here is how it looks when we're done:
We start with a collapsed tree view
We can then expand some nodes and the form will grow accordingly
And then we can re-collapse the nodes and expand more, the form adjusts again!
Forgive me for the French in the screenshots, it's the norm here in Quebec... We're obligated to do so!
You could trap the BeforeExpand and AfterExpand TreeView events to detect when the user changes the height of the node area. In that event handler, you need to find the bottom of the last node (using the Bounds property), then you finally need to change the height of the form.
Ensure that the TreeView's Anchor property includes both top and bottom, so that it grows with the form.
Of course the form has to be taller than than the TreeView. The bottom node's Bounds.Bottom property won't be exactly the bottom of the treeview, so my example below inflates this first by the height difference between the TreeView and form, then secondly by the difference between the client height of the TreeView, and the total height of the TreeView. It works correctly at my end.
You'd assign this same method to both the BeforeExpand and AfterExpand events. Note that it finds the last node by iterating through the nodes to find the bottom one; you'd want to check to make sure that this is guaranteed to give you the last node.
EDIT: You need to tell the tree to scroll to display the first node before starting any of this, for it to work consistently: hence the EnsureVisible() call.
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