I have an application which uses an UltraTree in Outlook mode which has worked well over the years however i am hitting some performance issues which I am trying to get to the bottom of.
It Outlook mode it appears that I have to add node using the parentNode.Add() method to get the column set created correctly for the new node which I do and then set a number fof attributes for the node (cell values etc). I have traced the code and added timers to find what seems to be taking the time and have narrowed it down to a single line which sets
node.Override.ShowExpansionIndicator = ShowExpansionIndicator.CheckOnExpand;
For about 16K nodes this one line increases the time to display the tree from 6 seconds to over 20 seconds yet to me it shouldn't actually cause anything to happen? I have the source code for the UltraTree but cannot see what is happening when this flag is set - does it trigger other events? I have begin / End Update around the entire operation but that doesn't help.
I was hooping I could set the flag for the parent node and have it filter down but that doesn't work either. Any suggestions most welcome.
I also find it odd that there does not appear to be a way to add a range of nodes in one go when working in Outlook mode - well you can but there doesn't appear to be a way to create all of the nodes, set their cell values and tags and then add to the parent node as the column set is not set for the new node until it is added to the parent (as far as I can tell).
Hi Mike, exactly your last point,. The total quantity of nodes in the tree could be very large so I took the decision early on that it was not worth while populating a branch until such time as the user attempted to expand it. I am therefore handling the BeforeExpand and populating any children if there are any, updating the Expansion Indicator based on this. There are however items being added to the tree which can never have children and as such I am setting those to 'Never' as part of the load of that node. The SQL query to recover the data is pretty quick but I have found that it can take quite some time to populate / display the tree if you add a lot of nodes.
Is it possible to create and add a range of nodes in Outlook mode? I can't see a way of doing this but I guess there may be a function I have not yet found to associate a column set with a new node (or range of nodes) before adding the nodes to their parent.
May I ask why you are using ShowExpansionIndicator.CheckOnExpand? The purpose of this setting is to optimize the loading of the tree when using DataBinding. But it sounds like you are manually adding the nodes to your tree using node.Nodes.Add(). The point of CheckOnExpand is that it allows all nodes in the tree to show an expansion indication and then the tree doesn't actually check to see if there are child nodes until the user or something else expands the node. That way, the tree doesn't have to access the data data source to determine if that node has any child nodes, which can be an expensive process. As opposed to CheckOnDisplay, which would have to force all nodes to load their child nodes in order to determine whether the expansion indicator is needed whenever that node is displayed on-screen, even before the user expands it. So ShowExpansionIndicator.CheckOnExpand doesn't really make a lot of sense for an unbound tree, since there's no data source to access and the node already knows if it has child nodes instantly, since that information is right in memory. If CheckOnExand is somehow slowing things down, then I agree that sounds like a problem, and maybe a bug. But using that setting for an unbound tree doesn't make sense, anyway, so I'm not sure it's worth pursuing. Unless I am missing something. :) EDIT: Oh... there is one other reason to use ShowExpansionIndicator.CheckOnExpand. If you are not populating all of the tree nodes up-front and you are handling the BeforeExpand event to populate the child nodes as-needed. Are you doing that?
Hi Andrew,
My thanks for your reply. In response to your questions...
1. The performance issue seems to happen as soon as I change the state of the 'ShowExpansionIndicator' flag - I have a timer around the loading of the nodes and this shows the time increases from 4 seconds to 24 seconds if I change the state of this flag.
2. They ill be a mixture however in this worst case scenario they were all parents and the default tree setting was set to 'CheckOnDisplay'. I have since changed the setting for the tree itself to be CheckOnDemand and this has fixed the issue in this specific case - however out of interest I changed all of my nodes to be bottom level children which caused my code to then set the ShowExpansionIndicator to 'Never' and the performance issue returned! So it seems to be the case that changing the state of this flag causes something behind the scenes to happen during the initial load even though I have Begin/End Update emabled.
3. The nodes are being added dynamically - initially as the control is loaded and subsequently on response to a Refresh button. Performance is the same in both cases.
As per your suggestion I have changed the initial setting for this flag which has helped other than as reported below. I did try adding a range of nodes but my tree is in Outlook mode - perhaps I am missing something but I cannot just create a new node as in
UltraTreeNode newNode = new UltraTreeNode()
...and then set the various column values as the node does not know about the columns - from what I can see I have to use the 'AddNode' function of the tree / parent node to ensure the column set is applied to the new node and I can set values. If you know different please let me know as I have not found a way to do this so far and AddRange would be far cleaner.
At this time I only set the override value IF the node has no possibility of having children which does help but there is always the possibility that all (or a large number) of the top level nodes have no children which would cause the performance issue to return.
Hello Chris,
I have been investigating into the behavior you are seeing, and I believe a little more information is needed in this case to get to the bottom of the performance issue you are seeing. I have some questions for you below.
1. At what point is this performance issue happening? It seems like it is in the population of the 16,000 nodes that you have mentioned, but I would just like to confirm.
2. Are the 16,000 nodes all parent nodes or are they children of another parent node(s)?
3. Are the 16,000 nodes being added dynamically, or is this performance issue happening right at the start / the initial population of the tree?
With the above questions, I do still have a couple of recommendations for you on this, as the UltraTree.Nodes collection as well as the UltraTreeNode.Nodes collections do have an AddRange method, taking an UltraTreeNode[], and so it is certainly possible to add multiple nodes at the same time. Would just need to populate an UltraTreeNode[] first and then pass that to the AddRange method.
Another thing I am seeing in this case is that it appears that you are potentially setting the ShowExpansionIndicator for each UltraTreeNode.Override and it is possible this could be creating a performance issue. This can be set on the tree itself instead by setting the UltraTree.Override.ShowExpansionIndicator property. This will filter down into each node.
Please let me know if you have any other questions or concerns on this matter.