Hi yogesjoshi,
Refer below sample.
HTML
<asp:GridView runat="server" ID="gvEmployees" />
Namespaces
C#
using System.Data;
using System.Reflection;
VB.Net
Imports System.Data
Imports System.Reflection
Code
C#
protected void Page_Load(object sender, EventArgs e)
{
List<Employee> employees = new List<Employee>();
List<EmployeeDepartments> departments = new List<EmployeeDepartments>();
departments.Add(new EmployeeDepartments { Mark = 48, Department = "Physics" });
departments.Add(new EmployeeDepartments { Mark = 45, Department = "Chemistry" });
employees.Add(new Employee { Id = 1, Name = "John Hammond", EmployeeDetails = departments });
departments = new List<EmployeeDepartments>();
departments.Add(new EmployeeDepartments { Mark = 50, Department = "Mathmatics" });
departments.Add(new EmployeeDepartments { Mark = 49, Department = "Biology" });
employees.Add(new Employee { Id = 2, Name = "Mudassar Khan", EmployeeDetails = departments });
gvEmployees.DataSource = CreateNestedDataTable<Employee, EmployeeDepartments>(employees, "EmployeeDetails");
gvEmployees.DataBind();
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public List<EmployeeDepartments> EmployeeDetails { get; set; }
}
public class EmployeeDepartments
{
public string Department { get; set; }
public int Mark { get; set; }
}
public DataTable CreateNestedDataTable<TOuter, TInner>(IEnumerable<TOuter> list, string innerListPropertyName)
{
PropertyInfo[] outerProperties = typeof(TOuter).GetProperties().Where(pi => pi.Name != innerListPropertyName).ToArray();
PropertyInfo[] innerProperties = typeof(TInner).GetProperties();
MethodInfo innerListGetter = typeof(TOuter).GetProperty(innerListPropertyName).GetGetMethod(true);
DataTable table = new DataTable();
foreach (PropertyInfo pi in outerProperties)
{
table.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType);
}
foreach (PropertyInfo pi in innerProperties)
{
table.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType);
}
// iterate through outer items
foreach (TOuter outerItem in list)
{
var innerList = innerListGetter.Invoke(outerItem, null) as IEnumerable<TInner>;
if (innerList == null || innerList.Count() == 0)
{
// outer item has no inner items
DataRow row = table.NewRow();
foreach (PropertyInfo pi in outerProperties)
{
row[pi.Name] = pi.GetValue(outerItem, null) ?? DBNull.Value;
}
table.Rows.Add(row);
}
else
{
// iterate through inner items
foreach (object innerItem in innerList)
{
DataRow row = table.NewRow();
foreach (PropertyInfo pi in outerProperties)
{
row[pi.Name] = pi.GetValue(outerItem, null) ?? DBNull.Value;
}
foreach (PropertyInfo pi in innerProperties)
{
row[pi.Name] = pi.GetValue(innerItem, null) ?? DBNull.Value;
}
table.Rows.Add(row);
}
}
}
return table;
}
VB.Net
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim employees As List(Of Employee) = New List(Of Employee)()
Dim departments As List(Of EmployeeDepartments) = New List(Of EmployeeDepartments)()
departments.Add(New EmployeeDepartments With {
.Mark = 48,
.Department = "Physics"
})
departments.Add(New EmployeeDepartments With {
.Mark = 45,
.Department = "Chemistry"
})
employees.Add(New Employee With {
.Id = 1,
.Name = "John Hammond",
.EmployeeDetails = departments
})
departments = New List(Of EmployeeDepartments)()
departments.Add(New EmployeeDepartments With {
.Mark = 50,
.Department = "Mathmatics"
})
departments.Add(New EmployeeDepartments With {
.Mark = 49,
.Department = "Biology"
})
employees.Add(New Employee With {
.Id = 2,
.Name = "Mudassar Khan",
.EmployeeDetails = departments
})
gvEmployees.DataSource = CreateNestedDataTable(Of Employee, EmployeeDepartments)(employees, "EmployeeDetails")
gvEmployees.DataBind()
End Sub
Public Class Employee
Public Property Id As Integer
Public Property Name As String
Public Property EmployeeDetails As List(Of EmployeeDepartments)
End Class
Public Class EmployeeDepartments
Public Property Department As String
Public Property Mark As Integer
End Class
Public Function CreateNestedDataTable(Of TOuter, TInner)(ByVal list As IEnumerable(Of TOuter), ByVal innerListPropertyName As String) As DataTable
Dim outerProperties As PropertyInfo() = GetType(TOuter).GetProperties().Where(Function(pi) pi.Name <> innerListPropertyName).ToArray()
Dim innerProperties As PropertyInfo() = GetType(TInner).GetProperties()
Dim innerListGetter As MethodInfo = GetType(TOuter).GetProperty(innerListPropertyName).GetGetMethod(True)
Dim table As DataTable = New DataTable()
For Each pi As PropertyInfo In outerProperties
table.Columns.Add(pi.Name, If(Nullable.GetUnderlyingType(pi.PropertyType), pi.PropertyType))
Next
For Each pi As PropertyInfo In innerProperties
table.Columns.Add(pi.Name, If(Nullable.GetUnderlyingType(pi.PropertyType), pi.PropertyType))
Next
For Each outerItem As TOuter In list
Dim innerList = TryCast(innerListGetter.Invoke(outerItem, Nothing), IEnumerable(Of TInner))
If innerList Is Nothing OrElse innerList.Count() = 0 Then
Dim row As DataRow = table.NewRow()
For Each pi As PropertyInfo In outerProperties
row(pi.Name) = If(pi.GetValue(outerItem, Nothing), DBNull.Value)
Next
table.Rows.Add(row)
Else
For Each innerItem As Object In innerList
Dim row As DataRow = table.NewRow()
For Each pi As PropertyInfo In outerProperties
row(pi.Name) = If(pi.GetValue(outerItem, Nothing), DBNull.Value)
Next
For Each pi As PropertyInfo In innerProperties
row(pi.Name) = If(pi.GetValue(innerItem, Nothing), DBNull.Value)
Next
table.Rows.Add(row)
Next
End If
Next
Return table
End Function
Screenshot