This is a migrated thread and some comments may be shown as answers.

Child nodes loaded on demand

13 Answers 287 Views
Treeview
This is a migrated thread and some comments may be shown as answers.
Sonya L
Top achievements
Rank 1
Sonya L asked on 10 Nov 2010, 04:00 PM
I have a situation where I want to create a treeview that has 4 levels.  I want to immediately load the first two levels, and only load levels 3 and 4 for a particular level 2 node when it is expanded.  I would like all of these nodes to be bound to a datatable(s) for ease of updating the data.  What would be the best way to accomplish this?  I am experimenting with both related tables in a hierarchy, and a self-referencing table, but haven't seen the exact results I am looking for.  Thanks for your help!

13 Answers, 1 is accepted

Sort by
0
Richard Slade
Top achievements
Rank 2
answered on 10 Nov 2010, 05:32 PM
Hello Sonya, 

You can use the LoadOnDemand feature of the RadTreeView for all child nodes, and get the child nodes that you need from the database as the NodeExpandedChanged event is firing. 

For more information, please refer to this documentation link

Hope that helps
Richard
0
Sonya L
Top achievements
Rank 1
answered on 10 Nov 2010, 05:50 PM
Is there a way to have the child nodes (levels 3 and 4) bound to a datatable, rather than creating them manually, as in the example?
0
Richard Slade
Top achievements
Rank 2
answered on 10 Nov 2010, 05:59 PM
Hello Sonya, 

As far as I'm aware, you cannot mix bound and unbound modes in this control. You would need to create them all manually, though you could get the levels 3 and 4 from the database and iterate over a reader or object collection that had been brought in from the database. 

hope this helps
Richard
0
Emanuel Varga
Top achievements
Rank 1
answered on 10 Nov 2010, 06:20 PM
Hello Sonya,

I would suggest something different, to use some middle tier logic, more precisely a binding list, and load all the data from the db in that binding list, please take a look at the following example:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Telerik.WinControls.UI;
 
namespace TreeViewLazyLoad
{
    public partial class Form1 : Form
    {
        private RadTreeView radTreeView1;
        private NodesList nodes;
        public Form1()
        {
            InitializeComponent();
            this.Controls.Add(radTreeView1 = new RadTreeView());
            radTreeView1.Dock = DockStyle.Fill;
        }
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            radTreeView1.LoadOnDemand = true;
            radTreeView1.NodeExpandedChanged += new RadTreeView.TreeViewEventHandler(radTreeView1_NodeExpandedChanged);
            nodes = new NodesList();
            nodes.GetFirstLevel();
            nodes.GetSecondLevel();
            radTreeView1.DataSource = nodes;
            radTreeView1.ParentIDMember = "ParentId";
            radTreeView1.ValueMember = "Id";
            radTreeView1.DisplayMember = "Name";
        }
 
        void radTreeView1_NodeExpandedChanged(object sender, RadTreeViewEventArgs e)
        {
            if (e.Node.Nodes.Count == 0)
            {
                var node = e.Node.DataBoundItem as Node;
                nodes.GetChildNodesForNode(node.Id);
            }
        }
    }
 
    public class Node
    {
        public int Id
        {
            get;
            set;
        }
 
        public int ParentId
        {
            get;
            set;
        }
 
        public string Name
        {
            get;
            set;
        }
    }
 
    public class NodesList : BindingList<Node>
    {
        public NodesList()
        {
        }
 
        public void GetFirstLevel()
        {
            for (int i = 0; i < 4; i++)
            {
                this.Add(new Node
                {
                    Id = i,
                    Name = "Name" + i,
                    ParentId = i
                });
            }
        }
 
        public void GetSecondLevel()
        {
            for (int i = 4; i < 8; i++)
            {
                this.Add(new Node
                {
                    Id = i,
                    Name = "Name" + i,
                    ParentId = i - 4
                });
            }
        }
 
        public void GetChildNodesForNode(int id)
        {
            var startIndex = this.Count;
            for (int i = startIndex; i < startIndex + 4; i++)
            {
                this.Add(new Node
                {
                    Id = i,
                    Name = "Name" + i,
                    ParentId = id
                });
            }
        }
    }
}

Basically here, I'm loading the first 2 levels, and after that on node expand just get the data from the db and add it to the list.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Richard Slade
Top achievements
Rank 2
answered on 10 Nov 2010, 06:23 PM
Hi All,

I agree. I hadn't thought of that and beleive that this solution should work well for your scenario

All the best
Richard
0
Sonya L
Top achievements
Rank 1
answered on 10 Nov 2010, 07:04 PM
I'll try that, thanks!
0
Emanuel Varga
Top achievements
Rank 1
answered on 10 Nov 2010, 07:06 PM
Glad to be able to help,

If you have any more questions please just let me know, and if the question has been solved, please mark the question as answered, so that others can find the answers to their questions faster.

Best Regards,
Emanuel Varga
0
Sonya L
Top achievements
Rank 1
answered on 11 Nov 2010, 08:02 PM
This example seems to work well, thanks!  Now I am trying to clear out the Binding List, and reload it based on a user action, but the tree does not display anything.  When the app first loads, I load the Binding List as in the example, and it works fine.  When I want to change the contents of the list, I set the tree's datasource to Nothing, clear the list, reload the binding list, and rebind it to the tree.  When I do this, the tree is blank.  What could I be missing?  Thanks!
0
Emanuel Varga
Top achievements
Rank 1
answered on 11 Nov 2010, 10:36 PM
Hello Sonya,

Why are you clearing the list? Why are you setting the datasource to nothing(null)?
Because it is a bindinglist, it will notify the tree on changes so you don't have to remove the datasource, just change the data inside the bindinglist.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
Telerik WinForms MVP
0
Sonya L
Top achievements
Rank 1
answered on 11 Nov 2010, 11:41 PM
I want to show a different tree, that is why I am clearing the list.  Basically, the user can pick different 'views' of the data, so the tree has to change entirely.
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 11 Nov 2010, 11:57 PM
Hello again,

Based on what you were saying I've updated the example, please tell me if something should be different:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Telerik.WinControls.UI;
 
public partial class Form1 : Form
{
    private RadTreeView radTreeView1;
    private NodesList nodes;
    private int view;
 
    public Form1()
    {
        InitializeComponent();
        this.Controls.Add(radTreeView1 = new RadTreeView());
        radTreeView1.Dock = DockStyle.Fill;
 
        var view1Button = new RadButton();
        view1Button.Text = "View1";
        view1Button.Click += new EventHandler(view1Button_Click);
        view1Button.Dock = DockStyle.Bottom;
        this.Controls.Add(view1Button);
 
        var view2Button = new RadButton();
        view2Button.Text = "View2";
        view2Button.Click += new EventHandler(view2Button_Click);
        view2Button.Dock = DockStyle.Bottom;
        this.Controls.Add(view2Button);
    }
 
    void view1Button_Click(object sender, EventArgs e)
    {
        ReloadData(1);
    }
 
    void view2Button_Click(object sender, EventArgs e)
    {
        ReloadData(2);
    }
 
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        radTreeView1.LoadOnDemand = true;
        radTreeView1.NodeExpandedChanged += new RadTreeView.TreeViewEventHandler(radTreeView1_NodeExpandedChanged);
        nodes = new NodesList();
        ReloadData(1);
        radTreeView1.DataSource = nodes;
        radTreeView1.ParentIDMember = "ParentId";
        radTreeView1.ValueMember = "Id";
        radTreeView1.DisplayMember = "Name";
    }
 
    private void ReloadData(int view)
    {
        radTreeView1.DataSource = null;
        nodes.Clear();
        this.view = view;
        nodes.GetFirstLevel(view);
        nodes.GetSecondLevel(view);
        radTreeView1.DataSource = nodes;
    }
 
    void radTreeView1_NodeExpandedChanged(object sender, RadTreeViewEventArgs e)
    {
        if (e.Node.Nodes.Count == 0)
        {
            var node = e.Node.DataBoundItem as Node;
            nodes.GetChildNodesForNode(node.Id, view);
        }
    }
}
 
public class Node
{
    public int Id
    {
        get;
        set;
    }
 
    public int ParentId
    {
        get;
        set;
    }
 
    public string Name
    {
        get;
        set;
    }
}
 
public class NodesList : BindingList<Node>
{
    public NodesList()
    {
    }
 
    public void GetFirstLevel(int view)
    {
        for (int i = 0; i < 4; i++)
        {
            this.Add(new Node
            {
                Id = i + view,
                Name = "Name" + i + view,
                ParentId = i + view
            });
        }
    }
 
    public void GetSecondLevel(int view)
    {
        for (int i = 4; i < 8; i++)
        {
            this.Add(new Node
            {
                Id = i + view,
                Name = "Name" + i + view,
                ParentId = i + view - 4
            });
        }
    }
 
    public void GetChildNodesForNode(int id, int view)
    {
        var startIndex = this.Count;
        for (int i = startIndex; i < startIndex + 4; i++)
        {
            this.Add(new Node
            {
                Id = (i + view),
                Name = "Name" + i + view,
                ParentId = id
            });
        }
    }
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga

Telerik WinForms MVP
0
Stefan
Telerik team
answered on 16 Nov 2010, 05:02 PM
Hello,

Thank you all for writing.

Sonya, I hope that you find the solution provided by Emanuel helpful. Please let us know if you need further assistance.

Emanuel, thank you for your help.

Sincerely yours,
Stefan
the Telerik team
See What's New in RadControls for WinForms in Q3 2010 on Wednesday, November 17, 11am Eastern Time: Register here>>
0
Sonya L
Top achievements
Rank 1
answered on 17 Nov 2010, 11:13 PM
Emanuel

Thanks for your help.  I was able to get it working with the following modifications.  For some reason, setting the datasource to null just caused a blank treeview.  Also, without the Begin/End Update, the app would hang when I tried to change views.  It seems to work now though.  Thanks!

private void ReloadData(int view)
    {
//added this
radTreeView1.BeginUpdate();

//replaced this
        //radTreeView1.DataSource = null;
radTreeView1.Nodes.Clear();

        nodes.Clear();
        this.view = view;
        nodes.GetFirstLevel(view);
        nodes.GetSecondLevel(view);

//removed this
        //radTreeView1.DataSource = nodes;

//added this
radTreeView1.EndUpdate();
    }
private void ReloadData(int view)
    {
    //added this
    radTreeView1.BeginUpdate();
 
    //replaced this
        //radTreeView1.DataSource = null;
    radTreeView1.Nodes.Clear();
 
        nodes.Clear();
        this.view = view;
        nodes.GetFirstLevel(view);
        nodes.GetSecondLevel(view);
 
    //removed this
        //radTreeView1.DataSource = nodes;
 
    //added this
    radTreeView1.EndUpdate();
    }


private void ReloadData(int view)
    {
//added this
radTreeView1.BeginUpdate();

//replaced this
        //radTreeView1.DataSource = null;
radTreeView1.Nodes.Clear();

        nodes.Clear();
        this.view = view;
        nodes.GetFirstLevel(view);
        nodes.GetSecondLevel(view);

//removed this
        //radTreeView1.DataSource = nodes;

//added this
radTreeView1.EndUpdate();
  
Tags
Treeview
Asked by
Sonya L
Top achievements
Rank 1
Answers by
Richard Slade
Top achievements
Rank 2
Sonya L
Top achievements
Rank 1
Emanuel Varga
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or