Treeview load time

Oct 22, 2012 at 5:59 PM

My tree view structure is about 1.3 MB based on request size and i need to load it in the expanded way. Right now it takes about 5 seconds to fetch the treeview nodes but it takes 38 seconds to just expand each and every node at the client side. All nodes need to be expanded because user wants to move sections from one to the other. 

Is there any way to improve this?

Please see below template code from .cshtml

@Html.TreeViewFor(
                    m => m.Sections,
                    i => i == 0 ? "Children" : null,
                    ExternalContainerType.span,
                    "filetree treeview-red",
                    new object[] 
                    {
                        _S.L<ALCS_POC.Models.Taxonomy>(h => 
                            "<span class='folder'>" + h.DisplayFor(m => m.Name).ToString()+"</span><span>"+h.HiddenFor(m => m.id).ToString()+"</span>" )
                    },
                    (x, y) => x is ALCS_POC.Models.PresentationClassfication ? 0 : 1,
                 "filetree treeview-black",
                    new object[] 
                    {
                        _S.L<ALCS_POC.Models.Taxonomy>(h => string.Format(
                            "<div class='folder' >{0} {1} {2} {3} {4} {5} {6} {7}  </div>", 
                            
                            
                            h.TypedEditDisplayFor(m => m.Name, simpleClick: true).ToString(),
                           
                            h.MyCustomTreeViewDeleteButton(Url.Content("~/Content/folder_delete_16.png"), 
                                ManipulationButtonStyle.Image, new Dictionary<string,object> { {"title","Delete this section and remove document association"} }).ToString(), 
                            h.TreeViewAddButton(0, Url.Content("~/Content/folder_add_16.png"), 
                                ManipulationButtonStyle.Image,new Dictionary<string,object> { {"title","Add a new child section"} }).ToString(),
                            
                            h.Hidden("IsFolder", true).ToString(),
                            
                                                           
                            h.HiddenFor(m=>m.id).ToString(),
                            h.HiddenFor(m=>m.ParentId).ToString(),
                            h.HiddenFor(m=>m.isDocumentExists).ToString(),
                            h.HiddenFor(m=>m.id).ToString()
                            
                            ))
                            

                    },
                    (x, y) => x is ALCS_POC.Models.Taxonomy ? 0 : 1,
                    TreeViewMode.InitializeEdit,
                    (x) => "allnodes",
                    (x, y) => TreeViewItemStatus.initializeShow
             ,
             new TreeViewOptions()
             {
                 Animated = 2,
                 Unique = true,
                 Opacity = 1,
                 CanMove = true,
                 CanAdd = true,
                 Persist = TreeViewPersistencyMode.Cookie,
                 CookieId = "treeview_edit"
             }

Coordinator
Oct 24, 2012 at 1:41 PM
Edited Oct 24, 2012 at 2:36 PM

Hi meethrishi123,

What you say appears quite strange, since the tree is firstly rendered opened and then all closed nodes are closed, so rendering all nodes open should be faster. Have yoiu tried with all nodes closed? Maybe it appears immediately...but the page is still running in background and it is "frozen". Pls verify this and verify if the tree with all nodes closed respond to your commands or it is "frozen" for the same 38 seconds.

 

The above is for the first rendering, because for the other renderingd the information are taken from the cookie since you set persistency to cookie. Since you use the tree in edit mode which nodes are open or closed is persisted also without the help of the cookie. So please set persistency to EditOnly

The point is that putting CanMove = true slower a lot the tree, so this option cannot be used for huge trees. How many nodes do you have and ho many levels of nesting do you have ? With the same number of nodes, if nesting increases the tree becomes slower to load. 

Pls try putting CanMove = false and let me know if the time improve, so I can locate the origin of the problem. 

Fetching time is fast because the tree is sent just as nested ul and li nodes and the content of each node. All structures needed to make the tree works are built on the client side. Enabling The CanMove capability means to process each single node of the tree to enable its moving capability 

You can load the tree via ajax to avoid blocking the page while the tree is loading, however still this way 38 seconds doesnt appear to me an acceptable time

Oct 25, 2012 at 7:30 AM

Thanks for the reply. However here are my observations

1. CanMove = false can not be set because, i need to be able to manipulate the treeview by rearranging the nodes to adjust as per user requirements.

2. There are 200 nodes in treeview with 3 levels

3. To avoid page freezing, i am already loading treeivew in a JQuery dialog via Ajax.

4. is it possible to load treeview like

a. Load only root nodes in initial display

b. User clicks on Expand button on a node and then only that section is expanded after loading content via AJAX

c. this step repeats on each node where user is clicking.

 

Thanks for your help

Coordinator
Oct 25, 2012 at 1:37 PM

First of all try to set : 

Persist = TreeViewPersistencyMode.EditOnly

so you avoid reading the cookie that might be the cause of the problem.

 

Then set CanMove=false just to make an experiment an to see if the and how much the performace improve.

You can do  ajax loading by sending data in json format from the server and by creating childnodes that you then populate with the data contained in the json content received, by using the Client Side interface of the Tree: http://mvccontrolstoolkit.codeplex.com/wikipage?title=Client%20Side%20Handling%20of%20Items%20Controls

 

Let me know the result of setting persistency to editOnly and canMove to false, and then I will give you more details on how to orgainize ajax loading

Nov 16, 2012 at 4:20 PM

 

The EditOnly does NOT improve the performance as expected. the  gain is very little.

CanMove improves the performance but does not serve the purpose. i want the organization capability of tree view using drag and drop.

 

Also, the "SAve" functionality that submits the form containing the treeview, takes a LOT of time to submit the tree view.

 

Any help is appreciated...

Coordinator
Nov 17, 2012 at 12:54 AM

So in order to improve the loading time the only way is to load just the first levels of the tree and then loading other branches the first time they are opened as I suggested in my previous post. I will post more details in the week end.

 

About the save time consider that if there are 200 nodes each node cost you 3 input fields+the input fileds you put in the template...so you are submitting about 1000 input fields.

 

The only solution ito improve performance is to decrease this number...This can be done by splitting the tree edit process in several different operations. For instance in a firt page the user might edit just the top level branches. Then In order to edit a secon level branch the user click a link in one of the first level nodes that open the branche into a different page. This might solve also the load time performance problem, an might simplify a lot the editing of the tree for the user since it is not easy to edit a 200 nodes tree that is ain a single web page.

There are also more complex tree-splitting solutions. Let me know if the above is acceptable for your application.

 

 

Nov 17, 2012 at 2:55 AM
Thanks for your help. Yes I will wait for the details over the weekend. Also, I feel that I Should try the complex operations that you mentioned to see if it serves my purpose. So any comments/input that you provide for the same will be much appreciated !
Coordinator
Nov 18, 2012 at 6:43 PM

Well In the next release of the Mvc Controls Toolkit I will modify the TreeView Helper so that nodes will be enabled to move only when their father node is opened the first time, this will decrease the load time to the case when CanSort is false, because the time needed to move -enable the nodes will not be spent all on loading time. I will sent you a copy of the new bits as soon it will be ready (maybe end next week)

 

That said the problem of the save time CANNOT BE SOLVED with any improvement in the helper, it is due essentially to the high numbers of input fileds involved. So the only way is to reduce this number someway.

Thus the best way to have both problems soved (load time and save time) is by loading only partially the tree and then dynamically adding other nodes with some mechanism. I will list some of them:

  1. Load just the first two levels of the tree, and then load the third level dynamically first time use open a second node. This way also the save time will be improved since only opened nodes will be saved. Once a second level node is opened you must marke it someway, for instance by writing something into an hidden field. When you will save the modified node into a db you have to rememer that ONLY the third level nodes whose father has been tagged must be saved to DB, because all other for sure was not touched by the user.
  2. Page the first level nodes, this way you can limit their number to say 3-4 and decrease the whole tree size. Maybe this will not improve a lot...however. It is the simplest solution
  3. Filter all nodes in all levels against a relevancy criterion (last inserted.....or something else) T the beginning just all most relevant are inserted in a level. Then by clicking some button all siblings of the "relevant" nodes will be loaded. This solution is similar to solution 1 but it is more complex to program. However it is the best solution for the user. Also in this case you have to tag the nodes whose children have been completely loaded in order to save the tree in the right way.

That said you may perform the dynamic loading of nodes in solution 1 and 3 by placing an event handler in a div or other nocde that contains the tree. This handler must respond to the itemChange (see here) event where the eventData.ChangeType is equal to ItemOpened. Once you verify you are in the situation depicted you do:

  1. Verify if the node opened that is contained in eventData.ItemChanged has already been tagged. If yes all nodes have been already loaded no furthe processing is needed, otherwise continue.
  2. Do an ajax call to an action method to get a list of objects containing each information about anew  node to add. This objects might be obtained by serializing the relative .Net objects that represents the nodes. 
  3. When you receive the result of the call. For each object received you create a new child of the  eventData.ItemChanged node and fill its input fields adequately with informations taken from the javascript object you are processing. The new node creation can be done with: MvcControlsToolkit_TreeView_AddNew(root, templateChosen, [item], [after]), see here .The template  index to pass to the call(templateChosen) can be found by inspecting the object (for instance to see if it is a folder or a document). root is just the father of the new node, that is  eventData.ItemChanged. In order to locate the input fields where to put the various object properties you may add them some css classes, so you can locate them by performing newlyCreatedNode.find('.myCssClass'). If some of this fields are complex controls such as TypedTextBoxes or aTypedEditDisplay you can use their client side api to set their values as explained HERE.
Coordinator
Dec 14, 2012 at 6:42 PM

In the Next Rlease of the Mvc Controls Toolkit the load time of big trees will be improved because nodes are processed when they are opened, so it swill be acceptable to load big trees with closed nodes.