2016-07-21 53 views
0

我有一個模型叫類別具有遞歸(父子)之間的關係如下:ASP MVC 5 C#遞歸樹集團和縮進一個DropDownList

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; } 

    } 

我想以生成heirachaly分組一個下拉列表基於對父子的關係,我也可以選擇父組如下 - 基本上我想從父縮進孩子:

<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> 

我的表數據如下:

Id | ParentId | Name 
---------------------- 
1 | null | Cars 
2 | 1  | Toyota 
3 | 1  | Nissan 
4 | null | Fruits 
5 | 4  | Apples 
6 | 4  | Oranges 

目前我有以下LINQ查詢,但它只是生成按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 
    } 

我怎樣才能修改LINQ查詢,讓他們正確地分組並縮進時,它的使用Html.DropDownListFor呈現的。

我試着修改我的原始選擇列表來實現某種樹,如下所示,但我卡在EnumerateNodes方法。下面的原件是打印出我從以下網站http://www.codeproject.com/Articles/23949/Building-Trees-from-Lists-in-NET拉出的ul列表。我如何迭代它並返回每個項目,如果它的子項名稱附加--並添加到我的選擇列表中?

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>"); 
} 
+0

你在哪裏卡住了?如果你想知道如何創建dropdownlist,你可能想看看[在ASP.Net MVC中使用DropDownList的最佳編程實踐](http://stackoverflow.com/a/37819577/296861)。 – Win

+0

@win我知道如何創建列表,是如何編寫LINQ來獲取它們的組合和縮進。 – adam78

+1

[通過遞歸檢查父子關係C#構建樹型列表]可能的重複(http://stackoverflow.com/questions/15867478/build-tree-type-list-by-recursively-checking-parent-child-relationship -c-sharp) – Win

回答

0

您可以先選擇父類(其中ParentIdnull),然後爲每個父類別中,選擇它的子類。

public IEnumerable<SelectListItem> GetCategoriesSelectList() 
{ 
    var categories = _context.Category.ToList(); 
    // Initialise list and add first "All" item 
    List<SelectListItem> options = new List<SelectListItem> 
    { 
     new SelectListItem(){ Value = "0", Text = "All" } 
    }; 
    // Get the top level parents 
    var parents = categories.Where(x => x.ParentId == null); 
    foreach (var parent in parents) 
    { 
     // Add SelectListItem for the parent 
     options.Add(new SelectListItem() 
     { 
      Value = parent.Id.ToString(), 
      Text = parent.Name 
     }); 
     // Get the child items associated with the parent 
     var children = categories.Where(x => x.ParentId == parent.Id); 
     // Add SelectListItem for each child 
     foreach (var child in children) 
     { 
      options.Add(new SelectListItem() 
      { 
       Value = child.Id.ToString(), 
       Text = string.Format("--{0}",child.Name) 
      }); 
     } 
    } 
    return options; 
} 
+0

我得到錯誤'已經有一個打開的DataReader與這個命令相關聯,必須先關閉它。'在以下行foreach(var child in children)'。爲了解決我已經推薦'var categories = _context.Category;'到'var categories = _context.Category.ToList()'。 Theres還有一個錯誤行'var children = products.Where(x => x.ParentId == parent.Id);'這應該是'var children = categories.Where(x => x.ParentId == parent。 Id);'如果您修改答案,我可以將其標記爲解決方案。乾杯。 – adam78

+0

現在更新。 :) –