将List <t>排序为DropDownList </t>的多级类别导航

时间:2014-03-18 05:23:14

标签: c# asp.net .net asp.net-mvc

首先让我说明一下我的目标与实现目标之间的关系

Sorting

在控制器中,我以非常随机的未排序方式将所有类别分成单个通用列表

var categories = new List<Category>(this.categoryService.GetCategories())

每个类别都有4个属性,重要的是 ID ParentCategoryId SortOrder 文字

SortOrder 必须仅应用于层次结构中同级别的同级,并且子级必须始终位于其父级之下。 文字必须通过预先添加&#34; ..&#34;对于每个深度级别。

我希望在考虑到性能的情况下正确完成此操作,不要多次递归遍历大量列表。

感谢您的任何意见。

2 个答案:

答案 0 :(得分:7)

这可能不是最性能代码,但应该适用于 OP 的问题。

由于 OP 没有明确定义有问题的数据结构(模型),我将假设它是这样的:

public class Category {
  public int Id { get; set; }
  public int ParentCategoryId { get; set; }
  public int SortOrder { get; set; }
  public string Text { get; set; }
}

要将类别列表(List<Category>)排序为多级别类别,我们需要一个树状结构来保存数据。

首先,我会使用Category等新属性扩展模型(Level类)(以指示级别深度),Children(以保存子/子{ {1}})和Category(根据其级别显示类别文本):

DisplayText

注意:取决于您的偏好,您可以直接更改public class CategoryNode : Category { public CategoryNode(Category category) { Id = category.Id; ParentCategoryId = category.ParentCategoryId; SortOrder = category.SortOrder; Text = category.Text; } public CategoryTree Children { get; set; } public int Level { get; set;} public string DisplayText { get { // OP wants two-dots prefix per level return string.Concat(new string('.', Level*2), Text); } } } 类,而不是将其子类化为Category

接下来,我将定义一个类来包装名为CategoryNode的{​​{1}}集合,它是CategoryNode的简单包装器,它公开CategoryTree interace。我还在List<CategoryNode>中添加了一个IEnumerable方法,它将树状结构展平为一个列表。此方法可以方便地将数据绑定到单个列表(非分层)控件,例如Flatten()CategoryTree。最后,我还添加了一个名为DropDownList的静态创建方法,以根据给定的ListBox列表创建Create()的实例:

CatogoryTree

注意:再次,可以说,您可以直接使用Category,提取方法,并省去自己在这里创建新类的麻烦。你的电话。

有了所有部分,我现在可以使用以下代码将public class CategoryTree : IEnumerable<CategoryNode> { private List<CategoryNode> innerList = new List<CategoryNode>(); public CategoryTree(IEnumerable<CategoryNode> nodes) { innerList = new List<CategoryNode>(nodes); } public IEnumerator<CategoryNode> GetEnumerator() { return innerList.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public IEnumerable<CategoryNode> Flatten() { foreach(var category in innerList.OrderBy(o => o.SortOrder)) { yield return category; if (category.Children != null) { foreach(var child in category.Children.Flatten()) { yield return child; } } } } public static CategoryTree Create( IEnumerable<Category> categories, Func<Category, bool> parentPredicate, int level = 0) { var nodes = categories .Where(parentPredicate) .OrderBy(o => o.SortOrder) .Select(item => new CategoryNode(item) { Level = level, Children = Create(categories, o => o.ParentCategoryId == item.Id, level + 1) }); return new CategoryTree(nodes); } } List<CategoryNode>)列表转换为Category的多级列表,并展平该列表以将其绑定进入List<Category>

Category

演示(使用DropDownList):https://ideone.com/ejOfrr

答案 1 :(得分:0)

您是否尝试过实施字典结构?

如:

Dictionary<Categories, List<T>> dictionary = new Dictionary<Categories, List<T>>();

这可能符合您的要求。

此外,如果您想要一个已排序的类别结构,您可以实现一个SortedDictionary,其中Category为Key&amp;相应的列表作为值。