I have a Model called Category which has a recursive (parent child) relationship as follows:
public class Category: ITreeNode<Category>
{
public byte Id { get; set; }
public byte? ParentId { get; set; }
public string Name { get; set; }
public Category Parent { get; set; }
public IList<Category> Children { get; set; }
}
I want to generate a dropdownlist that is heirachaly grouped based on the parent child relations where I can also select the parent group as follows - basically I want to indent the children from the parent:
<select name="Category" id="Category">
<option value="0">All</option>
<option value="1">Cars</option>
<option value="2">--Toyota</option>
<option value="3">--Nissan</option>
<option value="4">Fruits</option>
<option value="5">--Apples</option>
<option value="6">--Oranges</option>
</select>
My Table data is as follows:
Id | ParentId | Name
----------------------
1 | null | Cars
2 | 1 | Toyota
3 | 1 | Nissan
4 | null | Fruits
5 | 4 | Apples
6 | 4 | Oranges
Currently I have the following LINQ query but it simply generates a normal dropdown ordered by id.
public IEnumerable<SelectListItem> GetCategoriesSelectList()
{
var categories = new List<SelectListItem>
{
new SelectListItem() {Value = "0", Text = "All" }
}.Concat(_context.Category.Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Name
}).OrderBy(x => x.Value).ToList());
return categories
}
How can I amend the LINQ query to get them correctly grouped and indented for when it's rendered using a Html.DropDownListFor.
I've tried to amend my original select list to achieve some kind of tree as follows but I'm stuck on the EnumerateNodes method. The original below is for printing out a ul list which I pulled from the following site http://www.codeproject.com/Articles/23949/Building-Trees-from-Lists-in-NET. How do I iterate through it and return each item, if its a child then append --
to the name and add to my select list?
public IEnumerable<SelectListItem> GetCategoriesSelectList()
{
IList<Category> listOfNodes = GetListOfNodes();
IList<Category> topLevelCategories = TreeHelper.ConvertTOForest(listOfNodes);
var cats = new List<SelectListItem>
{
new SelectListItem { Value = "0", Text = "All"}
};
foreach(var category in topLevelCategories) {
var catName = EnumerateNodes(category);
cats.Add(new SelectListItem { Value = category.Id.ToString(), Text = catName });
}
return cats;
}
private List<Category> GetListOfNodes()
{
List<Category> sourceCategories = _context.Category.ToList();
List<Category> categories = new List<Category>();
foreach (Category sourceCategory in sourceCategories)
{
Category s = new Category();
s.Id = sourceCategory.Id;
s.Name = sourceCategory.Name;
if (sourceCategory.ParentId != null)
{
s.Parent = new Category();
s.Parent.Id = (int)sourceCategory.ParentId;
}
categories.Add(s);
}
return categories;
}
private static string EnumerateNodes(Category parent)
{
if (category.Children.Count > 0) {
Response.Write("<ul>");
foreach(Category child in category.Children) {
EnumerateNodes(child);
}
Response.Write("</ul>");
}
Response.Write("</li>");
}