Hello,
I use Version 12.1 and have a problem with the performance when adding nodes. In my sample program I have the following code:
this.ultraTree1.BeginUpdate(); var watch = Stopwatch.StartNew(); this.ultraTree1.Nodes.Clear(); for(int i = 0; i < 5000; i++) { var node = new UltraTreeNode { Text = i.ToString() }; ultraTree1.Nodes.Add(node); var b = node.Bounds; // this needs the time } watch.Stop(); Debug.WriteLine(watch.ElapsedMilliseconds); this.ultraTree1.EndUpdate();
When I use it the first time the performace is ok. On my machine ElapsedMilliseconds ~ 400. The second time the ElapsedMilliseconds ~ 9000. Is their a solution to have a better performance when I use it the second time? In the real program I need the Bounds property to make some calculation how large is the necessary wiidth of the control to suppress the horizontal scroll bar.
Thanks Joachim
Hi Joachim,
I don't think you can check the bounds of a node inside of the BeginUpdate/EndUpdate block like this. The Bounds are calculated when the node is painted. So either the call to the Bounds property is causing the tree to paint (which defeats the purpose of BeginUpdate), or else the results of the Bounds property will not be accurate inside this loop.
So I think what you can do to make this code more efficient is to take the Bounds calculation out of the loop the delay it until afterward.This way the tree only have to paint once in order to calculate the bounds of every node. I changed the code like so and it's fast every time:
this.ultraTree1.BeginUpdate(); var watch = Stopwatch.StartNew(); this.ultraTree1.Nodes.Clear(); for (int i = 0; i < 5000; i++) { var node = new UltraTreeNode { Text = i.ToString() }; ultraTree1.Nodes.Add(node); //var b = node.Bounds; // this needs the time } watch.Stop(); Debug.WriteLine(watch.ElapsedMilliseconds); this.ultraTree1.EndUpdate(); this.ultraTree1.Update(); foreach (UltraTreeNode node in this.ultraTree1.Nodes) { var b = node.Bounds; // this needs the time }
Hi Mike,
you are right, then it's fast, but only when I have a flat tree. When I have child nodes then it's slow when I calculate it after the EndUpdate() call.
I have looked on the results for my calculation in the real programm. The result is the same, if I make the calculation before or after the EndUpdate. All nodes have the default font, I don't change something on the font.
My problem is now, that when I make the calculation before the EndUpdate the calculation of a large flat tree ist fast ONLY the first time I fill the tree. The second time it's slow (see my sample). Why? I think it's a problem in your code. When I make the calculation after the EndUpdate it's fast all the time (your solution).
When I have a large tree with child nodes it is only fast when I make the calculation before the EndUpdate (calculation result same) -> after EndUpdate is no solution for me. The following code works for me after I inserted the nodes, but I think it is not really good code.
this.ultraTree1.EndUpdate(); this.ultraTree1.Update(); this.ultraTree1.BeginUpdate(); this.CalculateMaximumWidth(this.ultraTree1.Nodes); this.ultraTree1.EndUpdate();
Possible that you have a better solution for that what I wan't. I have attach the tree control on a dropdown. When the user opens the drop-down I fill the tree depend on the text that entered in the dropdown texteditor. I wan't that the tree.Width is >= dropdowncontrol.Width. The greater value I calculate to avoid the horizontal scrollbar when in the tree all node levels are expanded.
Joachim
It is puzzling that the slowdown doesn't happen until the second time you populate the tree. I'm not sure why that happens. I would have to look into it in more detail, but I expect there probably is a good reason for it.
This is just a guess, but the problem probably occurs with child nodes because those nodes aren't visible - they are under parent nodes that are not expanded. So their bounds are meaningless in that case, anyway. Maybe what you need to do is... don't walk down into the child nodes collection unless the parent node is visible and expanded. Or... you could call the ExpandAll method to expand all nodes in the tree.