How to improve performance of populating a massive tree view?
If you really care about speed of populating a massive treeview, you should look into virtualTreeView (http://code.google.com/p/virtual-treeview/).
It's an open source treeview specifically designed to be virtual and maximize speed/memory for large treeviews.
It's an amazing component.
There is a common trick in tree views to improve the performance in this type of situation. When you refresh this tree view, only load the first level of hierarchy, and don't worry about any further levels. Instead, you can load each additional level at the time of expanding each node. Here's how to do it.
When you populate the first level, rather than continuing with loading each of its child nodes, instead just create 1 "dummy" child node with a nil
pointer in its Data
property - since each node is expected to have an object in the Data
property anyway. Then, monitor the OnExpanding
event of the tree view. When a node is expanded, it will check to see if this "dummy" child node exists or not. If so, then it knows it needs to load the child nodes.
When the first level of hierarchy is loaded...
var
X: Integer;
N, N2: TTreeNode;
O: TMyObject;
begin
for X := 0 to MyObjectList.Count - 1 do begin
O:= TMyObject(MyObjectList[X]); //Object which Node represents
N:= TreeView.Items.AddChild(nil, O.Caption);
N.Data:= O;
N2:= TreeView.Items.AddChild(N, '');
N2.Data:= nil; //To emphasize that there is no object on this node
end;
end;
Then, create an event handler for OnExpanding
...
procedure TForm1.TreeViewExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
N: TTreeNode;
begin
N:= Node.getFirstChild;
if N.Data = nil then begin
//Now we know this is a "dummy" node and needs to be populated with child nodes
N.Delete; //Delete this dummy node
LoadNextLevel(N); //Populates child nodes by iterating through master list
end;
end;
The only disadvantage to this trick is that all nodes which have not yet been expanded will have a +
next to them, even though there may not be any child nodes. If this is the case, then when the user clicks the +
to expand a node, the child node gets deleted and the +
disappears so the user knows there are no child nodes within that node.
Also, using BeginUpdate
and EndUpdate
in TreeView.Items
improves performance by not performing GUI updates until it's all done...
TreeView.Items.BeginUpdate;
try
//Refresh the tree
finally
TreeView.Items.EndUpdate;
end;