8
votes

This is a System.Windows.Forms.TreeView, not a WPF or Web TreeView.

I must be missing something, because I can't believe this is that difficult.

I've got a TreeView on my form. Loading all the data to populate the TreeView is very slow, so I want to load just the top-level nodes and then fill in the children as the user expands nodes. The problem is, if a node doesn't have any children it doesn't display the + sign next to the node, which means it can't be expanded, which means I can't capture an Expanding event to load the children.

Years ago when I was using PowerBuilder you would set a HasChildren (or similar) property to true to essentially 'lie' to the control and force it to display the + and you could then capture the Expanding event. I've not been able to figure out how to force a + to appear on a node when there are no child nodes.

I've tried an approach where I add a dummy node to each node and then on expanding check if the dummy node is present and remove it then load the children, but for various reasons that aren't worth getting into here that solution is not viable in my situation.

I've Googled for various combinations of c#, treeview, delayed, deferred, load, force, expansion, and a few other terms that escape me now with no luck.

P.S. I found the TreeViewAdv project on SourceForge, but I'd rather not introduce a new component into our environment if I can avoid it.

6
I've always used the dummy node method; it generally works pretty well. Can you tell us more about why it won't work for you?Charlie

6 Answers

4
votes

Load the first 2 levels at startup and load 2 levels down when a node is expanded.

2
votes

I agree with Chris, I've had to do this vary thing. Load the top nodes and then capture the click event, make sure the click was on a selected node, and then populate the node, and then finally expand it.

If it's required to have the plus, then load the top nodes and drop a dummy node in it. Make sure you capture the click or expand event, clear the nodes and then repopulate it.

1
votes

A possible solution is to stay one step ahead of the treeview:

private void Form1_Load(object sender, EventArgs e)
{
    // initialise the tree here
    var nodeSomething = treeView1.Nodes.Add("Something");
    nodeSomething.Nodes.Add("Something below something");

    treeView1.AfterExpand += AfterExpand;
}

private void AfterExpand(object sender, TreeViewEventArgs e)
{
    foreach (TreeNode node in e.Node.Nodes)
    {
        // skip if we have already loaded data for this node
        if (node.Tag != null) 
            continue;
        node.Tag = new object();
        node.Nodes.AddRange(GetDataForThisNode(node));
    }
}
0
votes

I've also wondered how to get the + to show up next to childless nodes, but I never found a good way. My solution was to handle the MouseDoubleClick event like so:

Private Sub tvwMain_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles tvwMain.MouseDoubleClick
    Dim oNode As TreeNode

    oNode = tvwMain.GetNodeAt(e.X, e.Y)

    If oNode IsNot Nothing Then
        If oNode.Nodes.Count = 0 Then
            'add children here
        End If
    End If
End Sub
0
votes

Have you tried enclosing your node additions in BeginUpdate()and EndUpdate() calls? This disables any painting and as such allows you to add a large number of nodes to the TreeView without as significant delays.

MSDN: TreeView.BeginUpdate Method

0
votes

You may have better luck using TreeViewAdv (on sourceforge).