1

I have this structure of List<Object>, to be specific it is a "CategoryItem" Object. Here's my declaration of "CategoryItem" Object.

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

Here's my sample data structure:

[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

My problem is, how do I step in each and every 'CategoryItem' object of my declared:

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

So that I can display it in an unordered list in html like this

  • WelcomeNC
    • CNC
    • Production
    • Administrative
      • NPower
    • Help
      • 7
        • CHLK
  • First

Is there a way to do this?


Cannot use order by in this select?

I have this query..

SELECT ClassId, Sum(TeachersCount) as NumCount
FROM ClassSubject 
GROUP BY ClassId 
ORDER BY NumCount

but when I run this, access pops up a box asking me the value of NumCount? But this is not a parameter, this is.. well this is the sum of teachers that can teach that class, and it is to be calculated. So why is access asking me for its (NumCount's) value?

What I want is to count the number of teacher in a class and order this by increasing value of teacher count, I think that's what my query does, but why is it asking me for value of NumCount? One more thing, if I remove this ORDER BY clause, it runs fine, without asking me the value of NumCount? So what's the problem?

4

5 に答える 5

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);
  }
}
于 2012-06-04T08:32:03.693 に答える
1

単純ではありませんが、単純な解決策は、リストを反復し、アイテムごとに、0になる前に親IDを呼び出す回数を数えることです<li>.

于 2012-06-04T08:32:33.973 に答える
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);
    }
}
于 2012-06-04T08:50:09.297 に答える
1

TreeView コントロールを見てみましょう。 http://msdn.microsoft.com/en-us/library/7a9swst5(v=vs.80).aspx

ASP.NET TreeView コントロールは、ユーザーにデータを階層構造で表示するように設計されています。ユーザーは、子ノードを含むことができる個々のノードを開くことができます。TreeView コントロールは XML データの表示に適していますが、階層で表現できるあらゆるデータに使用できます。

ご希望通りになると思います。

それ以外の場合は、リスト内の各アイテムを反復処理し、サブアイテムがさらにある場合とない場合がある各サブアイテムを再帰的に処理するだけです。トリッキーですが、最初だけです。

于 2012-06-04T08:29:51.493 に答える
0

再帰について読んでください。そこにはかなりの数のサンプルがあります。ウィキペディアにあるものは単純ですが、原則は同じです。1 つの「レベル」で問題を解決し、各サブレベルで同じメソッドを再帰的に呼び出します。

于 2012-06-04T08:25:07.773 に答える