LINQ を使用してそれを行う方法の例を次に示します。まずサンプルのデータテーブル。トップレベルのアイテムの親 ID は 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" });
データの各項目を表すクラス:
class Item {
public Int32 Id { get; set; }
public String Name { get; set; }
public IEnumerable<Item> Children { get; set; }
}
特定のアイテムの子を取得する関数:
IEnumerable<DataRow> GetChildren(DataTable dataTable, Int32 parentId) {
return dataTable
.Rows
.Cast<DataRow>()
.Where(row => row.Field<Int32>("ParentId") == parentId);
}
子コレクションを含むアイテムを作成する関数。この関数は、階層を下に再帰します。
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 };
}
最上位アイテムの行を取得する関数:
IEnumerable<DataRow> GetTopLevelRows(DataTable dataTable) {
return dataTable
.Rows
.Cast<DataRow>()
.Where(row => row.Field<Int32>("ParentId") == 0);
}
すべてを一緒に入れて:
var items = GetTopLevelRows(dataTable)
.Select(row => CreateItem(dataTable, row))
.ToList();