Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Is it possible to output the following HTML unordered list using recursion.

<ul>
    <li>1
        <ul>
            <li>5
                <ul>
                    <li>8</li>
                    <li>9</li>
                </ul>
            </li>
            <li>6</li>
        </ul>
    </li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>7</li>
</ul>

Where the original data is is held in the following list

        List<Page> pages = new List<Page>();

        pages.Add(new Page { Id = 1, pageId = 1, parentPageId = 0 });
        pages.Add(new Page { Id = 2, pageId = 2, parentPageId = 0 });
        pages.Add(new Page { Id = 3, pageId = 3, parentPageId = 0 });
        pages.Add(new Page { Id = 4, pageId = 4, parentPageId = 0 });
        pages.Add(new Page { Id = 5, pageId = 5, parentPageId = 1 });
        pages.Add(new Page { Id = 6, pageId = 6, parentPageId = 1 });
        pages.Add(new Page { Id = 7, pageId = 7, parentPageId = 0 });
        pages.Add(new Page { Id = 8, pageId = 8, parentPageId = 5 });
        pages.Add(new Page { Id = 9, pageId = 9, parentPageId = 5 });

where Page is

    public class Page
    {
        public int Id { get; set; }
        public int pageId { get; set; }
        public int parentPageId { get; set; }
    }

Here's what I have so far which of course doesn't completely work...

        foreach (var page in pages)
        {
            Console.WriteLine("<ul><li>{0}", page.pageId);
            WriteMenu(pages, page.pageId, page.parentPageId);  
        }


    public static void WriteMenu(List<Page> pages, int pageId, int parentPageId)
    {
        foreach (var page in pages)
        {
            if (page.parentPageId == pageId)
            {
                Console.WriteLine("<ul><li>{0}", page.pageId);
                WriteMenu(pages, page.pageId, page.parentPageId);
            }
        }
    }
share|improve this question

2 Answers 2

up vote 3 down vote accepted

How about:

public static bool WriteMenu(List<Page> pages, int parentId, int indent)
{
    string padding = new string(' ', indent * 8);
    bool writtenAny = false;
    foreach (var page in pages.Where(p => p.ParentPageId == parentId))
    {
        if (!writtenAny)
        {                
            Console.WriteLine();
            Console.WriteLine(padding + "<ul>");
            writtenAny = true;
        }
        Console.Write(padding + "    <li>{0}", page.PageId);
        if (WriteMenu(pages, page.PageId, indent + 1))
        {
            Console.WriteLine(padding + "    </li>");                
        }
        else
        {
            Console.WriteLine("</li>");
        }
    }        
    if (writtenAny)
    {
        Console.WriteLine(padding + "</ul>");
    }
    return writtenAny;
}    
...
WriteMenu(pages, 0, 0);
share|improve this answer
    
Its nearly there ... the 2,3,4,7 part is not as in my example. –  Nicholas Murray Aug 5 '10 at 16:42
    
@Nicholas: Okay, edited - I believe it now looks exactly like your example - except that your example left out item 6 for some reason ;) –  Jon Skeet Aug 5 '10 at 16:57
    
Excellent, thanks, had a bout of Hexakosioihexekontahexaphobia there... Sorry! –  Nicholas Murray Aug 5 '10 at 17:21

Sorry, missed the recursive bit on my first stab, this should get the results you want:

        Console.WriteLine("<ul>");
        foreach (var page in pages)
        {
            if (page.parentPageId == 0)
            {
                WriteMenu(pages, page);
            }
        }
        Console.WriteLine("</ul>");



    private static void WriteMenu(List<Page> pages, Page page)
    {
        Console.WriteLine("<li>" + page.pageId);

        var subpages = pages.Where(p => p.parentPageId == page.pageId);

        if (subpages.Count() > 0)
        {
            Console.WriteLine("<ul>");
            foreach (Page p in subpages)
            {
                if (pages.Count(x => x.parentPageId == p.pageId) > 0)
                    WriteMenu(pages, p);
                else
                    Console.WriteLine(string.Format("<li>{0}</li>", p.pageId));
            }
            Console.WriteLine("</ul>");
        }

        Console.WriteLine("</li>");
    }
share|improve this answer
    
@Nicholas You're welcome, glad it helped :D –  heisenberg Aug 5 '10 at 18:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.