Click here to Skip to main content
15,904,416 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have the following result set that was generated as the result of query in Sql Server. How can I convert this into Hierarchical datasource using (C#) or (Linq to SQL) so I can bind the resultset to ASP.NET Treeview control.
1	Parent1	  10	Child1	  501	GrandChild1	Text
1	Parent1	  20	Child2	  502	GrandChild2	Text
1	Parent1	  30	Child3	  503	GrandChild3	Text
1	Parent1	  40	Child4	  0	                Text
2	Parent2	  10	Child1	  505	GrandChild4	Text
2	Parent2	  10	Child1	  506	GrandChild5	Text
2	Parent2	  20	Child2	  507	GrandChild6	Text
2	Parent2	  30	Child3	  508	GrandChild7	Text
2	Parent2	  40	Child4	  0		        Text
Posted
Comments
BobJanova 31-May-12 11:57am    
What do the columns represent?

 
Share this answer
 
Comments
VJ Reddy 1-Jun-12 0:12am    
Good references. 5!
El_Codero 1-Jun-12 18:03pm    
Thank you Reddy :D!
The above data can be converted into a heirarchial data source with XML data using LINQ with GroupBy extension method, and then it can be bound to the TreeView as shown below:
C#
protected void Page_Load(object sender, EventArgs e)
{
    DataTable dt1 = new DataTable("DataTable1");
    dt1.Columns.Add("C1", typeof(string), null);
    dt1.Columns.Add("C2", typeof(string), null);
    dt1.Columns.Add("C3", typeof(string), null);
    dt1.Columns.Add("C4", typeof(string), null);
    dt1.Columns.Add("C5", typeof(string), null);
    dt1.Columns.Add("C6", typeof(string), null);
    dt1.Columns.Add("C7", typeof(string), null);
    dt1.Rows.Add("1", "Parent1", "10", "Child1", "501", "GrandChild1", "Text");
    dt1.Rows.Add("1", "Parent1", "20", "Child2", "502", "GrandChild2", "Text");
    dt1.Rows.Add("1", "Parent1", "30", "Child3", "503", "GrandChild3", "Text");
    dt1.Rows.Add("1", "Parent1", "40", "Child4", "0", "", "Text");
    dt1.Rows.Add("2", "Parent2", "10", "Child1", "505", "GrandChild4", "Text");
    dt1.Rows.Add("2", "Parent2", "10", "Child1", "506", "GrandChild5", "Text");
    dt1.Rows.Add("2", "Parent2", "20", "Child2", "507", "GrandChild6", "Text");
    dt1.Rows.Add("2", "Parent2", "30", "Child3", "508", "GrandChild7", "Text");
    dt1.Rows.Add("2", "Parent2", "40", "Child4", "0", "", "Text");

    XElement root = new XElement("Root");
    var query = dt1.AsEnumerable().GroupBy(dr => dr.Field<string>("C1")).Select(par => {
        XElement parent = new XElement("Parent");
        parent.Add(new XAttribute("Id", par.Key));
        parent.Add(new XAttribute("Name", par.First().Field<string>("C2")));
        par.GroupBy(dr1 => dr1.Field<string>("C3")).Select(ch => {
            XElement child = new XElement("Child");
            child.Add(new XAttribute("Id", ch.Key));
            child.Add(new XAttribute("Name", ch.First().Field<string>("C4")));
            ch.Select(gch => {
                if (gch.Field<string>("C5") != "0") {
                    XElement gChild = new XElement("GrandChild");
                    gChild.Add(new XAttribute("Id", gch.Field<string>("C5")));
                    gChild.Add(new XAttribute("Name", gch.Field<string>("C6")));
                    gChild.Add(new XAttribute("Value", gch.Field<string>("C7")));
                    child.Add(gChild);
                }
                return gch;
            }).Count();
            parent.Add(child);
            return ch;
        }
    ).Count();
        root.Add(parent);
        return par;
    }).Count();
    XmlDataSource1.Data = root.ToString();
}

The LINQ query is of deferred execution model, so that it will not be executed until it is iterated or a scalar method like Count is called on it.

Hence, in the above code Count extension method is used to force immediate execution of the query.

The ASP.NET markup for the TreeView is as follows:
ASP
<form id="form1" runat="server">
<div>
    <asp:TreeView ID="TreeView1" runat="server" DataSourceID="XmlDataSource1">
        <DataBindings>
            <asp:TreeNodeBinding DataMember="Parent" TextField="Name" ValueField="Id" />
            <asp:TreeNodeBinding DataMember="Child" TextField="Name" ValueField="Id" />
            <asp:TreeNodeBinding DataMember="GrandChild" TextField="Name" ValueField="Id" />
        </DataBindings>
    </asp:TreeView>

    <asp:XmlDataSource ID="XmlDataSource1" runat="server"
         XPath="Root/Parent"></asp:XmlDataSource>
</div>
</form>

The XML data generated by the LINQ query is as follows
XML
<Root>
  <Parent Id="1" Name="Parent1">
    <Child Id="10" Name="Child1">
      <GrandChild Id="501" Name="GrandChild1" Value="Text" />
    </Child>
    <Child Id="20" Name="Child2">
      <GrandChild Id="502" Name="GrandChild2" Value="Text" />
    </Child>
    <Child Id="30" Name="Child3">
      <GrandChild Id="503" Name="GrandChild3" Value="Text" />
    </Child>
    <Child Id="40" Name="Child4" />
  </Parent>
  <Parent Id="2" Name="Parent2">
    <Child Id="10" Name="Child1">
      <GrandChild Id="505" Name="GrandChild4" Value="Text" />
      <GrandChild Id="506" Name="GrandChild5" Value="Text" />
    </Child>
    <Child Id="20" Name="Child2">
      <GrandChild Id="507" Name="GrandChild6" Value="Text" />
    </Child>
    <Child Id="30" Name="Child3">
      <GrandChild Id="508" Name="GrandChild7" Value="Text" />
    </Child>
    <Child Id="40" Name="Child4" />
  </Parent>
</Root>


And the TreeView is as follows:
VB
Parent1
    Child1
        GrandChild1
    Child2
        GrandChild2
    Child3
        GrandChild3
    Child4
Parent2
    Child1
        GrandChild4
        GrandChild5
    Child2
        GrandChild6
    Child3
        GrandChild7
    Child4
 
Share this answer
 
v2
Comments
Espen Harlinn 1-Jun-12 4:15am    
Well done!!
VJ Reddy 1-Jun-12 5:49am    
Thank you, Espen :)
El_Codero 1-Jun-12 18:03pm    
Nice solution. My 5.
VJ Reddy 1-Jun-12 19:38pm    
Thank you, Björn :)
techyPra 4-Jun-12 9:40am    
Thank you VJ.This is exactly what I am looking for.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900