List 的递归读取

我有List这种结构,具体来说它是一个“CategoryItem”对象。 这是我的“CategoryItem”对象的声明。

 public class CategoryItem { public string Name { get; set; } public int CategoryID {get; set;} public int ParentID {get; set; } public List SubCategory {get; set;} } 

这是我的示例数据结构:

 [0] CategoryID: 249 Name: "WelcomeNC" ParentID: 0 SubCategory: length=4 [0] CategoryID: 250 Name: "CNC" ParentID: 249 SubCategory: length=0 [1] CategoryID: 251 Name: "Production" ParentID: 249 SubCategory: length=0 [2] CategoryID: 252 Name: "Administrative" ParentID: 249 SubCategory: length=1 [0] CategoryID: 261 Name: "NPower" ParentID: 252 SubCategory: length=0 [3] CategoryID: 253 Name: "Help" ParentID: 249 SubCategory: length=1 [0] CategoryID: 254 Name: "7" ParentID: 253 SubCategory: length=1 [0] CategoryID: 255 Name: "CHLK" ParentID: 254 SubCategory: length=0 [1] CategoryID: 111 Name: "First" ParentID: 0 SubCategory: length=0 

我的问题是,我如何介入我声明的每个’CategoryItem’对象:

 List categoryItems = new List(); 

这样我就可以在html中的无序列表中显示它

  • WelcomeNC
    • CNC
    • 生产
    • 行政的
      • 甲级
    • 救命
      • 7
        • CHLK
  • 第一

有没有办法做到这一点?

如果您的CategoryItem不包含其子项列表(如问题的第一个版本),我将首先构建一个字典,foreach CategoryID为您提供所有子类别项目,然后使用此字典递归打印所有项目并从父项为“0”的项开始。 假设Print是打印与项目关联的数据的指令,并且它是缩进级别的唯一参数,代码将如下所示:

  public static void PrintItems(List items) { Dictionary> dictOfChildren = new Dictionary>(); // loop through all the items grouping them according to their ParentID foreach (CategoryItem anItem in items) { List children; if (!dictOfChildren.TryGetValue(anItem.ParentID, out children)) { children = new List(); dictOfChildren[anItem.ParentID] = children; } children.Add(anItem); } // recursively print all the items starting from the ones with ParentID = 0 // the dictionary is passed to the method in order to be able to find the children of each item PrintItems(dictOfChildren["0"], dictOfChildren, 0); } private static void PrintItems(List list, Dictionary> dictOfChildren, int levelOfIndentation) { foreach (CategoryItem anItem in list) { // first print the current item anItem.Print(levelOfIndentation); // then recursively print all its children List children; if (dictOfChildren.TryGetValue(anItem.CategoryID, out children) && children.Count > 0) PrintItems(children, dictOfChildren, levelOfIndentation + 1); } } 

它不是真正的面向对象,但这应该给你一个关于方向的暗示。

编辑:

我看到你编辑了这个问题,现在你已经添加了SubCategory属性。 这使事情变得更简单,你可以简单地做:

 public static void PrintItems(List items) { // call a recursive method passing 0 as level of indentation PrintItems(items, 0); } public static void PrintItems(List items, int levelOfIndentation) { foreach (CategoryItem anItem in items) { // print the currentItem anItem.Print(levelOfIndentation); // increment the level of indentation and callk the same method for the children PrintItems(anItem.SubCategory, levelOfIndentation + 1); } } 

也许看一下TreeView控件? http://msdn.microsoft.com/en-us/library/7a9swst5(v=vs.80).aspx

ASP.NET TreeView控件旨在向用户呈现分层结构中的数据。 用户可以打开可以包含子节点的单个节点。 TreeView控件适用于显示XML数据,但可用于可在层次结构中表示的任何数据。

我想这将是你想要的。

否则,这是迭代列表中的每个项目并递归处理每个子项目的问题,这些子项目可能有也可能没有更多的子项目。 这很棘手,但只是一开始。

一个简单的不是最优但简单的解决方案就是迭代列表,并为每个项目计算你在其0之前调用其父ID的次数。那么你就知道你的

  • 必须具有多少级别的标识。

    您需要创建一个“呈现”类别项的递归方法。 此方法需要了解渲染中的级别或当前深度以纠正缩进:

     private void RenderCategory(HtmlTextWriter writer, CategoryItem item, int level) { writer.Write("
  • {1}
  • ", level * 5, HttpUtility.HtmlEncode(item.Name)); int nextLevel = ++level; foreach (CategoryItem child in item.SubCategories) { RenderCategory(writer, child, nextLevel); } }

    阅读递归 。 那里有很多样品。 维基百科上的那些很简单,但原理是相同的:在一个“级别”上解决问题,然后在每个子级上递归调用相同的方法。