Here is an example on how to do that using LINQ. First a sampe datatable. I assume that top-level items have a parent ID of 0.
var dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(Int32));
dataTable.Columns.Add("ParentId", typeof(Int32));
dataTable.Columns.Add("Name", typeof(String));
dataTable.Rows.Add(new Object[] { 1, 0, "A" });
dataTable.Rows.Add(new Object[] { 2, 1, "B" });
dataTable.Rows.Add(new Object[] { 3, 1, "C" });
dataTable.Rows.Add(new Object[] { 4, 0, "D" });
dataTable.Rows.Add(new Object[] { 5, 4, "E" });
A class to represent each item of data:
class Item {
public Int32 Id { get; set; }
public String Name { get; set; }
public IEnumerable<Item> Children { get; set; }
}
A function to get the children of a specific item:
IEnumerable<DataRow> GetChildren(DataTable dataTable, Int32 parentId) {
return dataTable
.Rows
.Cast<DataRow>()
.Where(row => row.Field<Int32>("ParentId") == parentId);
}
A function to create an item including the child collection. This function will recurse down the hierarchy:
Item CreateItem(DataTable dataTable, DataRow row) {
var id = row.Field<Int32>("Id");
var name = row.Field<String>("Name");
var children = GetChildren(dataTable, id)
.Select(r => CreateItem(dataTable, r))
.ToList();
return new Item { Id = id, Name = name, Children = children };
}
A function to get rows of the top-level items:
IEnumerable<DataRow> GetTopLevelRows(DataTable dataTable) {
return dataTable
.Rows
.Cast<DataRow>()
.Where(row => row.Field<Int32>("ParentId") == 0);
}
Putting it all together:
var items = GetTopLevelRows(dataTable)
.Select(row => CreateItem(dataTable, row))
.ToList();