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:
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:
<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
<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:
Parent1
Child1
GrandChild1
Child2
GrandChild2
Child3
GrandChild3
Child4
Parent2
Child1
GrandChild4
GrandChild5
Child2
GrandChild6
Child3
GrandChild7
Child4