How to bind database table to TreeView control ? ?


Hi,

Good day. I am having a table with the following columns and values


----------------------------------------
RootNode | NodeLevel | Parent | Name |
----------------------------------------
Y | 0 | Null | Country|
----------------------------------------
N | 1 | Country| USA |
----------------------------------------
N | 2 | USA | NJ |
----------------------------------------
N | 1 | Country| INDIA |
----------------------------------------
N | 2 | INDIA | AP |
----------------------------------------

How to show the parent / Childs in treeview control ? Can you please help me with necessay code as this is urgent for my project.

Advance ThanX for your time & patience.

Cheers,
Kishore

Comments

  • Kishore

    Based on the table you provided here is some sample code that will do the trick. You can see I used a hashtable in order to make reference to the nodes while inserting them. This saves time on having to search for the nodes on each insert. You wlil also notice I ordered the table by NodeLevel. This is a must or you will recieve errors becuase the parent node may not exist at the time of insert.
    [code]
    private TreeView tView = new TreeView();
    public void PopulateTree()
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    SqlConnection conn = new SqlConnection("data source=tstsvr;initial catalog=TreeTest;integrated security=SSPI;");

    new SqlDataAdapter("SELECT * FROM Nodes ORDER BY NodeLevel Asc", conn).Fill(dt);

    foreach (DataRow r in dt.Rows)
    {
    int nodeLvl = int.Parse(r["NodeLevel"].ToString());
    string nodeParent = r["Parent"].ToString();
    string nodeName = r["Name"].ToString();

    TreeNode tNode = new TreeNode(nodeName);
    ht.Add(nodeLvl.ToString() + nodeName, tNode);

    if (tView.Nodes.Count == 0)
    tView.Nodes.Add(tNode);
    else
    {
    nodeLvl --;
    ((TreeNode) ht[nodeLvl.ToString() + nodeParent]).Nodes.Add(tNode);
    }
    }
    ht.Clear();
    }
    [/code]

    Hope this helps.

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]


  • Dear emaino,

    ThanX for your sincere reply. Can you please help me in this simple task. Your code is working fine for the populating of "TreeView" control ("TreeView_1").

    I have another "TreeView" control ("TreeView_2") on the same form. When i have selected a node in the "TreeView_1", then the node with its childs must be appear in the second "TreeView_2" control. Can you please help me in this task with necessary code ?

    Advance ThanX for your time & patience.

    Cheers,
    Kishore
  • Kishore

    Here is a simple function attached to the afterSelect event of the first treeview and then will populate the second treeview.
    [code]
    private void tView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
    {
    tView2.Nodes.Clear();
    tView2.Nodes.Add((TreeNode)((TreeView) sender).SelectedNode.Clone());
    }
    [/code]

    Hope this helps.

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]


  • Hi,

    Good day. ThanX for your sincere replies. But ... There is a samll change in the table structure. The table structure look like this


    ------------------------------------
    NodeLevel | Parent | Name | Type
    ------------------------------------
    0 | Null | Country | Dir
    ------------------------------------
    1 | Country| USA | Dir
    ------------------------------------
    2 | USA | NJ | File
    ------------------------------------
    1 | Country| India | Dir
    ------------------------------------
    2 | India | AP | Dir
    ------------------------------------
    3 | AP | Hyd | File
    ------------------------------------


    The first "TreeView_1" control must be populated with only "DIRECTORIES & SUB-DIRECORIES not THE FILES (Type) from the dtabase table.

    If we click on the node of the 'TreeView_1" control then, the node & all its DIRECTORIES, SUB DIRECTORIES and THE FILES must be visible in the second "TreeView_2" control.

    Can you please suggest me the way with necessary code to perform this task.

    Advance ThanX for your time & patience.

    Many ThanX,
    Cheers,
    Kishore

  • Kishore

    Here is a solution. I have taken the previous code I gave you and modified it. This solution works, but is not perfect. There is one major vulnerability and that is that you can't have 2 nodes named the same thing with files, becuase the hashtable used as a reference point uses the name of the node as a key. There are ways around this, the first would be to create a custom class that inherits TreeNode and has some extra properties, let me know if you want help with this, but first take a look at this code to see if it helps.
    [code]
    private Hashtable htFiles = new Hashtable();
    private System.Windows.Forms.TreeView tView2;
    private TreeView tView = new TreeView();

    public void PopulateTree()
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    SqlConnection conn = new SqlConnection("data source=tstsvr;initial catalog=TreeTest;integrated security=SSPI;");

    new SqlDataAdapter("SELECT * FROM Nodes ORDER BY NodeLevel Asc", conn).Fill(dt);

    foreach (DataRow r in dt.Rows)
    {
    int nodeLvl = int.Parse(r["NodeLevel"].ToString());
    string nodeParent = r["Parent"].ToString().Trim();
    string nodeName = r["Name"].ToString().Trim();
    string nodeType = r["Type"].ToString().Trim().ToLower();

    TreeNode tNode = new TreeNode(nodeName);
    ht.Add(nodeLvl.ToString() + nodeName, tNode);

    if (nodeParent == "")
    tView.Nodes.Add(tNode);
    else if (nodeType == "file")
    {
    nodeLvl --;
    if (htFiles.ContainsKey(nodeParent))
    ((ArrayList) htFiles[nodeParent]).Add(tNode);
    else
    {
    ArrayList al = new ArrayList();
    al.Add(tNode);
    htFiles.Add(nodeParent,al);
    }
    }
    else
    {
    nodeLvl --;
    ((TreeNode) ht[nodeLvl.ToString() + nodeParent]).Nodes.Add(tNode);
    }
    }
    ht.Clear();
    }

    private void tView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
    {
    TreeNode tn = (TreeNode)((TreeView) sender).SelectedNode.Clone();
    tView2.Nodes.Clear();
    LoadNodeFiles(tn);
    tView2.Nodes.Add(tn);
    }

    private void LoadNodeFiles(TreeNode tn)
    {
    if (tn.Nodes.Count > 0)
    foreach (TreeNode n in tn.Nodes)
    LoadNodeFiles(n);

    if (htFiles.ContainsKey(tn.Text))
    {
    ArrayList al = (ArrayList) htFiles[tn.Text];
    for (int i=0; i<al.Count; i++)
    if (!tn.Nodes.Contains((TreeNode) al[i]))
    tn.Nodes.Add((TreeNode) al[i]);
    }
    }
    [/code]

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]


  • Dear Emaino,

    First of all ThanX for your sincere replies. Please let me know for the same purpose, if the table is like below one, there will be no problem at all. Can you please suggest the necessay code for this ?


    --------------------------------------------
    NodeID | ParentNodeID | Name | Type |
    --------------------------------------------
    1 | 0 | Country | Dir |
    --------------------------------------------
    2 | 1 | USA | Dir |
    --------------------------------------------
    3 | 2 | NJ | File |
    --------------------------------------------
    4 | 1 | India | Dir |
    --------------------------------------------
    5 | 4 | AP | File |
    --------------------------------------------
    6 | 0 | Cars | Dir |
    --------------------------------------------
    7 | 6 | Domestic | Dir |
    --------------------------------------------
    8 | 7 | Ford | File |
    --------------------------------------------
    9 | 6 | Import | Dir |
    --------------------------------------------
    10 | 9 | BMW | File |
    --------------------------------------------
    11 | 0 | Blue | File |
    --------------------------------------------
    12 | 0 | Red | File |
    --------------------------------------------


    Can you please suggest me the way for proceeding with this structure with necessary code ? Waiting for reply...

    Advance ThanX for your valueble time & patience.

    Cheers
    Kishore

  • Kishore

    This can easily be accomplished, but my one question is where do you want the root files to be displayed?


    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]

  • Here is a solution that will work with the following table. You will notice that I had to create a custom class that inherited the TreeNode class.

    [code]
    private Hashtable htFiles = new Hashtable();
    private System.Windows.Forms.TreeView tView2;
    private TreeView tView = new TreeView();
    public void PopulateTree()
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    SqlConnection conn = new SqlConnection("data source=tstsvr;initial catalog=TreeTest;integrated security=SSPI;");

    new SqlDataAdapter("SELECT * FROM Nodes ORDER BY ParentNodeID Asc", conn).Fill(dt);

    foreach (DataRow r in dt.Rows)
    {
    int nodeID = int.Parse(r["ID"].ToString());
    int nodeParent = int.Parse(r["ParentNodeID"].ToString());
    string nodeName = r["Name"].ToString().Trim();
    string nodeType = r["Type"].ToString().Trim().ToLower();

    CustomNode cNode = new CustomNode(nodeName, nodeID, nodeParent);
    ht.Add(nodeID, cNode);

    if (nodeParent == 0)
    tView.Nodes.Add(cNode);
    else if (nodeType == "file")
    {
    if (htFiles.ContainsKey(nodeParent))
    ((ArrayList) htFiles[nodeParent]).Add(cNode);
    else
    {
    ArrayList al = new ArrayList();
    al.Add(cNode);
    htFiles.Add(nodeParent,al);
    }
    }
    else
    ((CustomNode) ht[nodeParent]).Nodes.Add(cNode);
    }
    ht.Clear();
    }

    private void tView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
    {
    CustomNode tn = (CustomNode)((TreeView) sender).SelectedNode;
    tn = (CustomNode) tn.Clone();
    tView2.Nodes.Clear();
    LoadNodeFiles(tn);
    tView2.Nodes.Add(tn);
    tn.Expand();
    }

    private void LoadNodeFiles(CustomNode tn)
    {
    if (tn.Nodes.Count > 0)
    foreach (CustomNode n in tn.Nodes)
    LoadNodeFiles(n);

    if (htFiles.ContainsKey(tn.ID))
    {
    ArrayList al = (ArrayList) htFiles[tn.ID];
    for (int i=0; i<al.Count; i++)
    if (!tn.Nodes.Contains((CustomNode) al[i]))
    tn.Nodes.Add((CustomNode) al[i]);
    }
    }

    public class CustomNode : TreeNode
    {
    private int nid;
    public int ID
    {
    get {return nid;}
    set {nid = value;}
    }

    private int nparentid;
    public int ParentID
    {
    get {return nparentid;}
    set {nparentid = value;}
    }

    public override object Clone()
    {
    CustomNode cn = (CustomNode) base.Clone();
    cn.ID = nid;
    cn.ParentID = nparentid;
    return cn;
    }

    public CustomNode(string name, int id, int parentid)
    {
    base.Text = name;
    nid = id;
    nparentid = parentid;
    }

    public CustomNode()
    {
    }
    }
    [/code]
    Hopefully this helps.

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]

  • [b][red]This message was edited by kishore_peddi at 2003-9-30 7:16:2[/red][/b][hr]
    Hi emaino,

    ThanX for your replies & suggestions. (Small Modification is needed). In TreeView_1 control, if i select a node, then its Sub-nodes / Childs must appear. But in our program it is copying the selected node also. Can you please modify the code in such a way that, if i select a node in "treeView_1" control, then ITS CHILDS ONLY must appear not the slected node. Waiting for reply...

    EXAMPLE:-
    =======

    In "TreeView_1", we have

    Country
    |
    ---USA
    ---India

    and selected "Country" node then, in the "treeView_2" control we must have

    USA
    |
    ---NJ

    India
    |
    ---Orissa

    be displayed.

    Advance ThanX for your valueble time & patience.

    Cheers,
    Kishore


    : Here is a solution that will work with the following table. You will notice that I had to create a custom class that inherited the TreeNode class.

    [code]
    private Hashtable htFiles = new Hashtable();
    private System.Windows.Forms.TreeView tView2;
    private TreeView tView = new TreeView();
    public void PopulateTree()
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    SqlConnection conn = new SqlConnection("data source=tstsvr;initial catalog=TreeTest;integrated security=SSPI;");

    new SqlDataAdapter("SELECT * FROM Nodes ORDER BY ParentNodeID Asc", conn).Fill(dt);

    foreach (DataRow r in dt.Rows)
    {
    int nodeID = int.Parse(r["ID"].ToString());
    int nodeParent = int.Parse(r["ParentNodeID"].ToString());
    string nodeName = r["Name"].ToString().Trim();
    string nodeType = r["Type"].ToString().Trim().ToLower();

    CustomNode cNode = new CustomNode(nodeName, nodeID, nodeParent);
    ht.Add(nodeID, cNode);

    if (nodeParent == 0)
    tView.Nodes.Add(cNode);
    else if (nodeType == "file")
    {
    if (htFiles.ContainsKey(nodeParent))
    ((ArrayList) htFiles[nodeParent]).Add(cNode);
    else
    {
    ArrayList al = new ArrayList();
    al.Add(cNode);
    htFiles.Add(nodeParent,al);
    }
    }
    else
    ((CustomNode) ht[nodeParent]).Nodes.Add(cNode);
    }
    ht.Clear();
    }

    private void tView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
    {
    CustomNode tn = (CustomNode)((TreeView) sender).SelectedNode;
    tn = (CustomNode) tn.Clone();
    tView2.Nodes.Clear();
    LoadNodeFiles(tn);
    tView2.Nodes.Add(tn);
    tn.Expand();
    }

    private void LoadNodeFiles(CustomNode tn)
    {
    if (tn.Nodes.Count > 0)
    foreach (CustomNode n in tn.Nodes)
    LoadNodeFiles(n);

    if (htFiles.ContainsKey(tn.ID))
    {
    ArrayList al = (ArrayList) htFiles[tn.ID];
    for (int i=0; i<al.Count; i++)
    if (!tn.Nodes.Contains((CustomNode) al[i]))
    tn.Nodes.Add((CustomNode) al[i]);
    }
    }

    public class CustomNode : TreeNode
    {
    private int nid;
    public int ID
    {
    get {return nid;}
    set {nid = value;}
    }

    private int nparentid;
    public int ParentID
    {
    get {return nparentid;}
    set {nparentid = value;}
    }

    public override object Clone()
    {
    CustomNode cn = (CustomNode) base.Clone();
    cn.ID = nid;
    cn.ParentID = nparentid;
    return cn;
    }

    public CustomNode(string name, int id, int parentid)
    {
    base.Text = name;
    nid = id;
    nparentid = parentid;
    }

    public CustomNode()
    {
    }
    }
    [/code]

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]







  • Here you are.. The only thing I had to change was the following method. Hope this helps.
    [code]
    private void tView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
    {
    CustomNode tn = (CustomNode)((TreeView) sender).SelectedNode;
    tn = (CustomNode) tn.Clone();
    tView2.Nodes.Clear();

    foreach (CustomNode n in tn.Nodes)
    {
    LoadNodeFiles(n);
    tView2.Nodes.Add(n);
    n.Expand();
    }
    if (htFiles.ContainsKey(tn.ID))
    {
    ArrayList al = (ArrayList) htFiles[tn.ID];
    for (int i=0; i<al.Count; i++)
    if (!tn.Nodes.Contains((CustomNode) al[i]))
    tView2.Nodes.Add((CustomNode) al[i]);
    }
    }
    [/code]

    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]


  • Hi Emaino,

    Good day. Can i use same structure of code for creating the "Dynamic Menu" also ?

    The structure of the table "TM" looks like this


    -----------------------------------------
    MenuItemID | ParentMenuID | MenuItemName |
    -----------------------------------------
    1 | 0 | File |
    -----------------------------------------
    2 | 1 | Open |
    -----------------------------------------
    3 | 1 | Save |
    -----------------------------------------
    4 | 5 | Help .NET |
    -----------------------------------------
    5 | 0 | Help |
    -----------------------------------------
    6 | 4 | Help VB.NET |
    -----------------------------------------
    7 | 4 | Help C# |
    -----------------------------------------



    The main thing is, I want to have the events for each and every Menu Item. How it is possible ? Can you please suggest me the way for doing it.


    I have written the following code


    private System.Windows.Forms.MainMenu mainMenu1;

    private void Form1_Load(object sender, System.EventArgs e)
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    SqlConnection conn = new SqlConnection("server=SERVER;UID=nexalar;PWD=nexalar;Database=nexalar");

    new SqlDataAdapter("SELECT * FROM TM ORDER BY ParentMenuItemID Asc", conn).Fill(dt);

    foreach (DataRow r in dt.Rows)
    {
    int MenuItemID = int.Parse(r["MenuItemID"].ToString());
    int ParentMenuItemID = int.Parse(r["ParentMenuItemID"].ToString());
    string MenuItemName = r["MenuItemName"].ToString().Trim();

    CustomMenuItem cMenuItem = new CustomMenuItem(MenuItemName, MenuItemID, ParentMenuItemID);
    ht.Add(MenuItemID, cMenuItem);

    if (ParentMenuItemID == 0)
    {
    mainMenu1.MenuItems.Add(cMenuItem);

    }
    else
    {
    ((CustomMenuItem) ht[ParentMenuItemID]).MenuItems.Add(cMenuItem);
    }
    }
    ht.Clear();
    }

    public class CustomMenuItem : MenuItem
    {
    private int MenuItemID;
    public int ID
    {
    get {return MenuItemID;}
    set {MenuItemID = value;}
    }

    private int ParentMenuItemID;
    public int ParentID
    {
    get {return ParentMenuItemID;}
    set {ParentMenuItemID = value;}
    }

    public CustomMenuItem(string name, int id, int parentid)
    {
    base.Text = name;
    MenuItemID = id;
    ParentMenuItemID = parentid;
    }

    public CustomMenuItem()
    {
    }
    }


    Advance ThanX for your time & patience.

    Bye...
    Cheers,
    Kishore
  • Kishore

    This can be done, but which type of events are you looking for? Becuase most of these events are going to have to be staticly coded which kind of defeats the purpose of the dynamic creation.




    [size=3][italic]Eric Maino[/italic][/size]
    [b][blue]GVSU[/blue] Microsoft SA[/b]

  • Eric, I have seen your code below, which seems to help me a great deal.
    However, my table looks alittle different and I keep getting an error : Let me shopw you what my table looks like :
    NodeId, NodeName, TierNumber, NodeLevel, NodeDescription, NodeDisplayOrder, NodeParentName
    1, ShowCustomers,1,0,Show All Customer, Show Cusotmers,1,
    2,Options,1,0,Show Options,Options,2
    3,Maintenance,2,1,Show Maintenance Options,Maintenance,1,Options
    4,Password,2,1,Change Password,Password,2,Options

    The erros I get is on the line :
    ((TreeNode) ht[nodeLvl + nodeParent]).Nodes.Add(tNode);

    The error is :
    Additional information: Object reference not set to an instance of an object.

    Here is the code I have, which is very similar to what you have written :

    [code]
    private void loadTree()
    {
    OleDbDataAdapter daSnd = null;
    DataSet dsSnd = null;

    String dsNameSnd = "TreeView";
    bool eVal = dbCon.DbExecute (ref daSnd ,ref dsSnd, "SELECT * FROM TreeViewNodes ORDER BY NodeLevel", dsNameSnd);

    if (eVal == true)
    {
    DataTable dt = new DataTable();
    Hashtable ht = new Hashtable();

    daSnd.Fill(dt);
    foreach (DataRow dr in dt.Rows )
    {
    int nodeLvl = int.Parse(dr["NodeLevel"].ToString().Trim());
    String nodeName = dr["NodeName"].ToString().Trim();
    String nodeParent = dr["ParentNodeName"].ToString().Trim();
    TreeNode tNode = new TreeNode(nodeName);
    ht.Add(nodeLvl.ToString() + nodeName, tNode);
    if (tvInt.Nodes.Count == 0)
    {
    tvInt.Nodes.Add(tNode);
    }
    else
    {
    nodeLvl --;
    ((TreeNode) ht[nodeLvl + nodeParent]).Nodes.Add(tNode);
    }
    }
    ht.Clear();
    }
    }
    }


    Do you have an idea why I am getting that error message ?

    I was also wondering if there is a way I can attach a description to each node so when the mouse hovers above it, it will be displayed.

    Many thanks in advance.

    Tomarsh




    : [code]
    : private TreeView tView = new TreeView();
    : public void PopulateTree()
    : {
    : DataTable dt = new DataTable();
    : Hashtable ht = new Hashtable();
    :
    : SqlConnection conn = new SqlConnection("data source=tstsvr;initial catalog=TreeTest;integrated security=SSPI;");
    :
    : new SqlDataAdapter("SELECT * FROM Nodes ORDER BY NodeLevel Asc", conn).Fill(dt);
    :
    : foreach (DataRow r in dt.Rows)
    : {
    : int nodeLvl = int.Parse(r["NodeLevel"].ToString());
    : string nodeParent = r["Parent"].ToString();
    : string nodeName = r["Name"].ToString();
    :
    : TreeNode tNode = new TreeNode(nodeName);
    : ht.Add(nodeLvl.ToString() + nodeName, tNode);
    :
    : if (tView.Nodes.Count == 0)
    : tView.Nodes.Add(tNode);
    : else
    : {
    : nodeLvl --;
    : ((TreeNode) ht[nodeLvl.ToString() + nodeParent]).Nodes.Add(tNode);
    : }
    : }
    : ht.Clear();
    : }
    : [/code]
    :
    : Hope this helps.
    :
    : [size=3][italic]Eric Maino[/italic][/size]
    : [b][blue]GVSU[/blue] Microsoft SA[/b]
    :
    :

  • [size=3][color=Red][/color][/size]

    HI I am vamsy in the above mentioned code i got error (node level does not belongs to my database table i.e parent1)
    plz help my querie........
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories