List <object> </object>的递归读取

时间:2012-06-04 08:18:52

标签: c# .net list tree html-lists

我有List<Object>的这种结构,具体来说它是一个&#34; CategoryItem&#34;宾语。这是我对&#34; CategoryItem&#34;的声明。对象

public class CategoryItem
{
    public string Name { get; set; }
    public int CategoryID {get; set;}
    public int ParentID {get; set; }
    public List<CategoryItem> 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”&#39;我声明的对象:

List<CategoryItem> categoryItems = new List<CategoryItem>();

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

  • WelcomeNC
    • CNC
    • 生产
    • 管理
      • 甲级
    • 帮助
      • 7
        • CHLK
  • 第一

有办法做到这一点吗?

5 个答案:

答案 0 :(得分:1)

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

  

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

我认为这将是你想要的。

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

答案 1 :(得分:1)

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

private void RenderCategory(HtmlTextWriter writer, CategoryItem item, int level)
{
  writer.Write("<li style='padding-left: {0}px'>{1}</li>", 
    level * 5,
    HttpUtility.HtmlEncode(item.Name));

  int nextLevel = ++level;
  foreach (CategoryItem child in item.SubCategories)
  { 
    RenderCategory(writer, child, nextLevel);
  }
}

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

    public static void PrintItems(List<CategoryItem> items)
    {
        Dictionary<string, List<CategoryItem>> dictOfChildren = new Dictionary<string, List<CategoryItem>>();
        // loop through all the items grouping them according to their ParentID
        foreach (CategoryItem anItem in items)
        {
            List<CategoryItem> children;
            if (!dictOfChildren.TryGetValue(anItem.ParentID, out children))
            {
                children = new List<CategoryItem>();
                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<CategoryItem> list, Dictionary<string, List<CategoryItem>> dictOfChildren, int levelOfIndentation)
    {
        foreach (CategoryItem anItem in list)
        {
            // first print the current item
            anItem.Print(levelOfIndentation);
            // then recursively print all its children
            List<CategoryItem> children;
            if (dictOfChildren.TryGetValue(anItem.CategoryID, out children) &&
                children.Count > 0)
                PrintItems(children, dictOfChildren, levelOfIndentation + 1);
        }
    }

这不是真正的面向对象,但这应该会给你一个关于要遵循的方向的提示。

修改

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

public static void PrintItems(List<CategoryItem> items)
{
    // call a recursive method passing 0 as level of indentation
    PrintItems(items, 0);
}

public static void PrintItems(List<CategoryItem> 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);
    }
}

答案 4 :(得分:0)

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