Tree View on demand loading concept in 2011

13 posts, 0 answers
  1. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 19 Mar 2011 Link to this post

    How does the current NewNodesNeeded actually work?

    Does the event handler get called for each visible node to determine if the expand hint (+) should be showed?
    If yes, this is not a usable concept for me. I would like to give that indication without actually loading the children.

    When I load my root nodes, I already know if they have children (by grouping and count() in the database).
    The Idea now is to show the user how many children there are and let him decide if he wants to expand (and wait for the nodes to be loaded).

    Regards Erwin

  2. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 23 Mar 2011 Link to this post

    Hi Erwin,

    The new NodesNeeded event is fired only when a node is in expanded state and its Nodes collection is empty. You can expand a node that is currently not into view programmatically and the visibility state of the node will not be taken into consideration by the event handler. This gives us good performance, decreased possible recursion issues and simplified API which only has the NodesNeeded event.

    All the best,
    Julian Benkov
    the Telerik team
  3. UI for WinForms is Visual Studio 2017 Ready
  4. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 23 Mar 2011 Link to this post

    so how do you determine if the expand hint should be shown for a visible node (non expanded state) without calling the NodesNeeded Event?
  5. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 24 Mar 2011 Link to this post

    Hi erwin,

    The NodesNeeded event is fired initially when RadTreeView is loaded. If the Parent property is null, this means that the event is fired for the root level, so we pass the desired root node(s) to the Nodes collection that comes from the event arguments. Further, the NodesNeeded is fired once again for each of the created root nodes even before we try to expand them. As a result, we load the children of the root nodes before we expand these root nodes and this is how the nodes know whether to show the expander or not. When we expand a root node, the NodesNeeded event is fired for each of the child nodes where we pass the children of the child nodes. So, the child nodes know whether to show the expander image or not as well.

    We will consider extending the Load-On-Demand feature, showing the expander element for each node.

    Best wishes,
    Julian Benkov
    the Telerik team

  6. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 24 Mar 2011 Link to this post

    Julian,

    that's exactly what I suspected. Unfortunately that makes the feature unusable for many scenarios. If you really care about performance, you can model the query so that when loading the root nodes, you already know if there are child nodes. That makes 1 roundtrip to the database instead of 30 or whatever visible root nodes you have.
    In my scenario, the demand loading with NodesNeeded is most of the times much slower than loading the tree in one go with no on demand loading at all, since that also requires just 1 roundtrip to the database. The thing is, that the round trip to a database including query parsing etc. is extremely expensive.
    Not that much of an issue though, when you still provide a way to manually load nodes on expand events. But see my other post about display glitches with that approach..

    regards
    Erwin
  7. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 29 Mar 2011 Link to this post

    Hi Erwin,

    I made also another solution of Load-On-Demand functionality using NodeExpandedChanged, CreateNode and NodeFormatting events:

    public partial class Form6 : Form
    {
        class LazyTreeNode : RadTreeNode
        {
            private bool loaded;
     
            public bool Loaded
            {
                get { return loaded; }
                set { loaded = value; }
            }
        }
     
        public Form6()
        {
            InitializeComponent();
            radTreeView1.ShowLines = true;
     
            using (radTreeView1.DeferRefresh())
            {
                for (int i = 0; i < 10; i++)
                {
                    radTreeView1.Nodes.Add("RootNode" + i.ToString());
                }
            }
        }
     
        private void radTreeView1_NodeExpandedChanged(object sender, Telerik.WinControls.UI.RadTreeViewEventArgs e)
        {
            LazyTreeNode node = e.Node as LazyTreeNode;
            if (node.Loaded)
            {
                return;
            }
     
            node.Nodes.BeginUpdate();
            for (int i = 0; i < 10; i++)
            {
                node.Nodes.Add("ChildNode" + i.ToString());
            }
            node.Nodes.EndUpdate();
            node.Loaded = true;
        }
     
        private void radTreeView1_CreateNode(object sender, Telerik.WinControls.UI.CreateTreeNodeEventArgs e)
        {
            e.Node = new LazyTreeNode();
        }
     
        private void radTreeView1_NodeFormatting(object sender, TreeNodeFormattingEventArgs e)
        {
            e.NodeElement.ExpanderElement.Visibility = Telerik.WinControls.ElementVisibility.Visible;
        }
    }

    This solution has a known issue concerning the indent of the RadTreeNodes at the different levels. In Q1 2011 SP1 the desired behavior will be natively supported by RadTreeView, the layout issue will be addressed and the NodeNeeded event will be raised only the currently visible and expanded level.

    Best wishes,
    Julian Benkov
    the Telerik team
  8. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 29 Mar 2011 Link to this post

    Thanks, Julian. that's roughly the method I used with prior versions but which now prevents upgrading my solution because of the indent problem. Looking forward to SP1 then.

    Regards
    Erwin
  9. Joel Kraft
    Joel Kraft avatar
    87 posts
    Member since:
    Jan 2004

    Posted 14 Apr 2011 Link to this post

    I would like to echo erwin's statement that this is not a usable concept in many circumstances (I too had implemented a similar lazy-load mechanism in previous versions).

    Is there an ETA for SP1? Will a work-around similar to the one presented be required or will there be a property to set when the NewNodesNeeded event gets fired (on node displayed versus on node expanded)?
  10. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 20 Apr 2011 Link to this post

    Hi Joel,

    You can download and use new Q1 2011 SP1 release. In the new improved implementation of load-on-demand functionality the NodesNeeded event is raised only for expanded parent node. This is the new default behavior of RadTreeView control, for other cases when you want to know the nodes for inner level in advance, then must set the new LazyMode property of treeview to false. We also added support to make RadTreeView work properly with the approach valid for the old version of RadTreeView control using Loaded property in this example:

    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
            this.radTreeView1.NodesNeeded += new NodesNeededEventHandler(radTreeView1_NodesNeeded);
     
            using (radTreeView1.DeferRefresh())
            {
                for (int i = 0; i < 10; i++)
                {
                    radTreeView1.Nodes.Add("RootNode" + i.ToString());
                }
            }
        }
     
        void radTreeView1_NodesNeeded(object sender, NodesNeededEventArgs e)
        {
             
        }
     
        private void radTreeView1_NodeExpandedChanged(object sender, Telerik.WinControls.UI.RadTreeViewEventArgs e)
        {
            LazyTreeNode node = e.Node as LazyTreeNode;
            if (node.Loaded)
            {
                return;
            }
     
            node.Nodes.BeginUpdate();
            for (int i = 0; i < 10; i++)
            {
                node.Nodes.Add("ChildNode" + i.ToString());
            }
            node.Nodes.EndUpdate();
            node.Loaded = true;
        }
     
        private void radTreeView1_CreateNode(object sender, Telerik.WinControls.UI.CreateTreeNodeEventArgs e)
        {
            e.Node = new LazyTreeNode();
        }
     
        class LazyTreeNode : RadTreeNode
        {
            private bool loaded;
     
            public bool Loaded
            {
                get { return loaded; }
                set { loaded = value; }
            }
        }
    }

    I hope this helps.

    All the best,
    Julian Benkov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  11. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 20 Apr 2011 Link to this post

    Thanks, Julian.

    I checked with the most trivial tree in my app and seems to work quite well.
    In other trees I'll have to work a bit on the load logic.

    I guess the release notes for SP1 should mention this as a breaking change compared to 2011Q1.

    Regards
    Erwin
  12. Calago
    Calago avatar
    66 posts
    Member since:
    Feb 2008

    Posted 04 May 2011 Link to this post

    Hello,

    When I use the new NodesNeedes event, I get 2 events when I start filling the root tree.
    Both e arguments have the e.parent set to null.

    Another question: When I use this event, I cannot dermine which node is calling the event.
    What I want is load the root three when the app starts, each created root node will call the nodesneeded event, so I can determine if I need to fill his nodes collection with nodes.
    But right now, when the nodesneeded event runs, I cannot deterine this.

    Can you please help?
    Regards,
    Jeroen
  13. erwin
    erwin avatar
    358 posts
    Member since:
    Dec 2006

    Posted 04 May 2011 Link to this post

    Jeroen,

    I do exaclty what you want to do with loading the root nodes when the control loads and loading child nodes on demand.

    If the parent is null, I just ignore the NodesNeeded handler.

    If the parent node is not null, I use it's Tag Property, where I previously stored the key to load child nodes.

    hope this helps.

    Erwin
  14. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 06 May 2011 Link to this post

    Hello A. Bennen,

    Like Erwin suggested, you can load root nodes outside the event handler and use the event for the internal Nodes collection:
    public partial class Form16 : Form
    {
        public Form16()
        {
            InitializeComponent();
     
            //root Nodes
            for (int i = 0; i < 50; i++)
            {
                RadTreeNode childNode = new RadTreeNode(string.Format("Node{0}", i));
                this.radTreeView1.Nodes.Add(childNode);
            }
        }
     
        private void radTreeView1_NodesNeeded(object sender, Telerik.WinControls.UI.NodesNeededEventArgs e)
        {
            if (e.Parent == null)
            {
                return;
            }
     
            for (int i = 0; i < 50; i++)
            {
                RadTreeNode childNode = new RadTreeNode(string.Format("Node{0}", i));
                e.Nodes.Add(childNode);
            }
        }
    }

     


    Kind regards,
    Julian Benkov
    the Telerik team
    Q1’11 SP1 of RadControls for WinForms is available for download; also available is the Q2'11 Roadmap for Telerik Windows Forms controls.
Back to Top
UI for WinForms is Visual Studio 2017 Ready