如何使用递归编程填充包含许多类别的列表框

The*_*Man 3 c# asp.net recursion linq-to-sql

我有一个类别表,它被设置为允许无限数量的子类别级别.我想模仿以下内容: 在此输入图像描述

应该澄清的是,子类别可以有子类别.例如父母 - > 1级 - > 2级 - > 3级等

我的类别表有两列,CategoryNameParentID.

在为产品分配正确的类别时,将使用此列表框.

我怎么写这个?

编辑

为了回应thedugas我必须修改你的答案,以适应我的情况.我发现了一些需要修复的错误,但下面是最终的工作解决方案.

protected void Page_Load(object sender, EventArgs e)
    {
        using (DataClasses1DataContext db = new DataClasses1DataContext())
        {

        var c = db.Categories.Select(x => x);

        List<Category> categories = new List<Category>();
        foreach (var n in c)
        {
            categories.Add(new Category()
            {
                categoryID = n.categoryID,
                title = n.title,
                parentID = n.parentID,
                isVisible = n.isVisible
            });
        }
        List<string> xx = new List<string>();

        foreach (Category cat in categories)
        {
            BuildCatString(string.Empty, cat, categories, xx);
        }

        ListBox1.DataSource = xx;
        ListBox1.DataBind();

    }
}

private void BuildCatString(string prefix, Category cat, IEnumerable<Category> categories, List<string> xx)
{
    if (cat.parentID == 0)
    {
        xx.Add(cat.title);
        prefix = cat.title;
    }

    var children = categories.Where(x => x.parentID == cat.categoryID);
    if (children.Count() == 0)
    {
        return;
    }

    foreach (Category child in children)
    {
        if(prefix.Any())
        {
        xx.Add(prefix + "/" + child.title);
        BuildCatString(prefix + "/" + child.title,
            child, categories, xx);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

这是几乎完成的工作: 在此输入图像描述

Eri*_*ert 7

尼克在评论另一个问题时问我如何在不使用任何递归的情况下使用LINQ to Objects解决这类问题.轻松完成.

让我们假设我们有一个Dictionary<Id, Category>将ID映射到类别.每个类别都有三个字段:Id,ParentId和Name.让我们假设ParentId可以为null,以标记那些"顶级"的类别.

所需的输出是一系列字符串,其中每个字符串都是该类别的"完全限定"名称.

解决方案很简单.我们首先定义一个辅助方法:

public static IEnumerable<Category> CategoryAndParents(this Dictionary<Id, Category> map, Id id)
{
    Id current = id;
    while(current != null)
    {
        Category category = map[current];
        yield return category;
        current = category.ParentId;
    }
}
Run Code Online (Sandbox Code Playgroud)

而这个辅助方法:

public static string FullName(this Dictionary<Id, Category> map, Id id)
{
    return map.CategoryAndParents(id)
              .Aggregate("", (string name, Category cat) =>
                cat.Name + (name == "" ? "" : @"/") + name);
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望避免可能低效的天真字符串连接:

public static string FullName(this Dictionary<Id, Category> map, Id id)
{
    return string.Join(@"/", map.CategoryAndParents(id)
                                .Select(cat=>cat.Name)
                                .Reverse());
}
Run Code Online (Sandbox Code Playgroud)

现在查询很简单:

fullNames = from id in map.Keys
            select map.FullName(id);
listBox.DataSource = fullNames.ToList();
Run Code Online (Sandbox Code Playgroud)

不需要递归.