0

I have a table in sql: table data goes like:

catid parentid catname
----- -------- -------------------
1     0        Operating Systems
2     1        Windows
3     1        Linux
4     5        Windows Server 2008 
5     2        Windows Server
6     1        Unix 

Parent id keeps its parent. For example; Windows Server 2008 comes first and belongs to Windows Server (its parent sometimes comes later).

In C# side i got that table in dataset, but could not solve rest.

for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
    TreeNode root = new TreeNode();
    TreeNode child = new TreeNode();
    if (ds.Tables[0].Rows[i]["parentid"] == 0)
    {

        root.Text = ds.Tables[0].Rows[i]["catname"];
        trview.Nodes.Add(root);
    }
    else
    {
        child.Text = ds.Tables[0].Rows[i]["catname"];
        root.ChildNodes.Add(child);                       
    }                             
}

How can i fill Treeview according to table. I could not solve how to design loop for it. If parentid is belong to a catid, it will be node of it.

Thank you for any advise or help

Kind Regards

josefh75
  • 3
  • 1
  • 3

3 Answers3

3

Iteration might not solve your problem. You can add all root-level nodes using iteration and then recursively add child nodes for each parent node. You can try the following:

private void BindTreeview()
{
    DataRow[] parentRows = mDataSet.Tables[0].Select("parentid = " + ROOT_PARENT_ID.ToString()); // # Get all root nodes

    foreach (DataRow row in parentRows) // # Add all root nodes to treeview and call for child nodes
    {
        TreeNode node = new TreeNode();
        node.Text = row["catname"].ToString();
        tvCategories.Nodes.Add(node);
        AddChildNodes((int)row["catid"], node);
    }
}

private void AddChildNodes(int catId, TreeNode node) // # Recursive method to add child nodes and call for child nodes of each child node
{
    DataRow[] childRows = mDataSet.Tables[0].Select("parentid = " + catId.ToString()); // # Get all child nodes of given node

    if (childRows.Length == 0) { return; } // # Recursion base case; if given node has no child nodes no more action is taken

    foreach (DataRow row in childRows)
    {
        TreeNode childNode = new TreeNode();
        childNode.Text = row["catname"].ToString();
        node.Nodes.Add(childNode);
        AddChildNodes((int)row["catid"], childNode);
    }
}

What it does: simple put; Finds root level categories and adds them to TreeView one by one, calling AddChildNodes method with added node and corresponding catid so that child nodes can be added. AddChildNodes method finds 1 level below childs of given catid and goes on with recursive calls for each found child until there are no more childs of a given node

This approach will work for your case, i just tested it. Just remember to replace:

  • mDataSet - with your DataSet instance
  • tvCategories - with your TreeView instance
Saro Taşciyan
  • 5,210
  • 5
  • 31
  • 50
  • Thank you for example and ideas. As far as i understand i need to use recursive function. If root has 5 element, and 400 rows for subcatagories randomly goes to parents. Recursion will affect page load time heavily in that case? Should i instead manually create treeview in asp.net template side instead? – josefh75 Dec 29 '13 at 11:11
  • @josefh75 well, recursion always works slower then iteration. If you have tried both solutions suggested by me and BartoszKP, you can profile them with different dummy data load and see if any efficiency consideration is necessary. But since you query all data only *once* and work on it over memory i don't think the performance would be bad – Saro Taşciyan Dec 29 '13 at 11:23
0

You can try this two pass algorithm. Using the Tag property isn't the cleanest way here, but this should give you an idea how to handle such tasks:

var id2node = new Dictionary<int, TreeNode>();

for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
    var node = new TreeNode();
    node.Text = ds.Tables[0].Rows[i]["catname"];
    node.Tag = ds.Tables[0].Rows[i]["parentid"];

    id2node.Add(ds.Tables[0].Rows[i]["catid"], node);
}

foreach (var node in id2node.Values)
{
    TreeNode parent = null;
    if (id2node.TryGetValue((int)node.Tag, out parent))
    {
        parent.ChildNodes.Add(node);
    }
    else
    {
        trview.Nodes.Add(node);
    }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
0

you may see this article in code project: Parent-Child-Hierarchical-Relational-Treeview

EDIT:

also check this: how-to-dynamically-populate-treeview-c

Community
  • 1
  • 1
S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61