views:

715

answers:

4

Hi everyone, I need to render a unordered list with the data obtained from database using asp.net/C#.My data looks something like this.

id     Name               Depth

1    ELECTRONICS             0

2    TELEVISIONS             1

3    Tube                   2

4    LCD                    2

5    Plasma                 2

6   Portable electronics    1

7   MP3 Player              2

8    Flash                  3

9    CD Players             2

10    2 Way Radio           2

using the above sample data I need to render an unordered list based on the depth, in the following format

<ul>
  <li>ELECTRONICS

<ul>

   <li>TELEVISIONS

  <ul>

    <li>TUBE</li>

    <li>LCD</li>

    <li>PLASMA</li>

  </ul>

   </li>

   <li>PORTABLE ELECTRONICS
  <ul>

    <li>MP3 PLAYERS

   <ul>

<li>FLASH</li>

   </ul>

    </li>

    <li>CD PLAYERS</li>

    <li>2 WAY RADIOS</li>

  </ul>

   </li>

</ul>

</li>

</ul>

Above data is just a sample,I have a huge recordset which has to be converted to unordered list.Could someone please give me an idea on how to achieve this?

UPDATE: I've updated my code which generates unordered list to the following .

int lastDepth = -1;
        int numUL = 0;

        StringBuilder output = new StringBuilder();


        foreach (DataRow row in ds.Tables[0].Rows)
        {

            int currentDepth = Convert.ToInt32(row["Depth"]);

            if (lastDepth < currentDepth)
            {
                if (currentDepth == 0)
                {
                    output.Append("<ul class=\"simpleTree\">");
                    output.AppendFormat("<li class=\"root\"><span><a href=\"#\" title=\"root\">root</a></span><ul><li class=\"open\" ><span><a href=\"#\" title={1}>{0}</a></span>", row["name"],row["id"]);
                }
                else
                {
                    output.Append("<ul>");
                    if(currentDepth==1)
                    output.AppendFormat("<li><span>{0}</span>", row["name"]);
                    else
                        output.AppendFormat("<li><span class=\"text\"><a href=\"#\" title={1}>{0}</a></span>", row["name"], row["id"]);
                }
                numUL++;
            }
            else if (lastDepth > currentDepth)
            {
                output.Append("</li></ul></li>");
                if(currentDepth==1)
                output.AppendFormat("<li><span>{0}</span>", row["name"]);
                else
                    output.AppendFormat("<li><span class=\"text\"><a href=\"#\" title={1}>{0}</a></span>", row["name"], row["id"]);
                numUL--;
            }
            else if (lastDepth > -1)
            {
                output.Append("</li>");
                output.AppendFormat("<li><span class=\"text\"><a href=\"#\" title={1}>{0}</a></span>", row["name"],row["id"]);
            }


            lastDepth = currentDepth;
        }

        for (int i = 1; i <= numUL+1; i++)
        {
            output.Append("</li></ul>");
        }

With the above code my unordered list looks like this.

<ul class="simpleTree">
<li class="root">
<span><a href="#" title="root">root</a></span>
<ul>
<li class="open" >
<span><a href="#" title=1>ELECTRONICS</a></span>
<ul>
<li>
<span>TELEVISIONS</span>
<ul>
<li>
<span class="text"><a href="#" title=3>TUBE</a></span>
</li>
<li>
<span class="text"><a href="#" title=4>LCD</a></span>
</li>
<li><span class="text"><a href="#" title=5>PLASMA</a></span>
</li>
</ul>
</li>
<li>
<span>PORTABLE ELECTRONICS</span>
<ul>
<li>
<span class="text"><a href="#" title=7>MP3 PLAYERS</a></span>
<ul>
<li>
<span class="text"><a href="#" title=8>FLASH</a></span>
</li>
</ul>
</li>
<li>
<span class="text"><a href="#" title=9>CD PLAYERS</a></span>
</li>
<li>
<span class="text"><a href="#" title=10>2 WAY RADIOS</a></span>
</li>
</ul>
</li></ul>
</li></ul>
</li></ul>

Thanks.

+1  A: 

Use the Repeater Control.

Samples:

MSDN Documentation

Edit: Didn't notice the part about depth, use the Treeview Control instead, look at the part about binding to a database.

BarrettJ
The repeater control is almost deprecated by the ListView control.
Chris Marisic
Hi Barrett,Once I present the unordered list in the form of a treeview,I need to apply some js to provide drag and drop functionality to it.Is that possible if i use the treeview control instead?Also I've around 500 records in the db.If i present them as a treeview is that not going to be a load on the server and create delays across postbacks?
kranthi
@kranthi: For drag-and-drop and rich features you might try a 3rd-party component like Telerik http://www.telerik.com/products/aspnet-ajax/treeview.aspx
John K
+1  A: 

Unless you're using .NET 2.0 you should use the ListView Control.

Using ASP.NET 3.5's ListView and DataPager Controls: Displaying Data with the ListView

Chris Marisic
A: 

You could do something like this in code and then output the result to a Literal control on your page:

int lastDepth = -1;
int numUL = 0;

StringBuilder output = new StringBuilder();


foreach (DataRow row in yourDataTable.Rows) {

    int currentDepth = row["Depth"];

    if (lastDepth < currentDepth) {
        output.append("<ul>");
        numUL++
    }
    else if (lastDepth > currentDepth) {
        output.append("</li></ul></li>");
        numUL--
    }
    else if (lastDepth > -1) {
        output.append("</li>");
    }

    output.appendformat("<li class=\"depth-{1}\">{0}", row["name"], currentDepth);

    lastDepth = currentDepth;
}

for (int i = 1;i <= numUL;i++)
{
    output.append("</li></ul>");
}



yourLiteralControl.Text = output.toString();

Update: I made it so that it will put in a css class on the list items related to the depth as requested in the comments.

patmortech
I really want to DV this but it's a technically correct statement however I would absolutely never recommend doing this. There are controls meant for this, I'd rather bind a ForEach loop in the aspx page before this.
Chris Marisic
Hi Chris,why would you not recommend the above method?
kranthi
Would love to hear why you think this is so bad compared to a bunch of nested ListViews (which I'm not sure would even work in this instance without a lot of extra code, considering the flexible amount of depth to his lists). And whether you put this foreach loop in the code behind or in the ASPX page itself, there's really no difference unless you are not buffering the output of your page.
patmortech
Because code like this is basically unmaintainable. If he needs nested lists you can render ListViews inside of a ListView. Where as the ListView aside from being easier to extend also offers the ability to have the included event support and of course true databinding is a huge plus.
Chris Marisic
I've implemented this exact scenario before with a ListView that renders a ListView and then I bind the parent listview a List of Lists and it's done.
Chris Marisic
I've got nothing against ListViews. But in this particular case, looking at the structure of his data (no parent/child relationship other than the order in the dataset), I'm drawing a blank as to how you can simply bind this exact dataset to a nested 4-level deep set of ListViews and get what you want. That's why I wrote this in code. If you could post the code you would use in your answer it would help to see what I'm missing (because the example you link to is not the same as this situation).
patmortech
@patmortech,with the code you have provided I'am implementing unorderedlist.Would you be able to suggest any improvements to the code in order to generate the 'li' elements with different cssclasses assigned to them.Please check the following link http://stackoverflow.com/questions/2361561/assigning-a-cssclass-to-each-li-element-in-an-unordered-list-programmatically,where I've posted another question regarding the generated unorderedlist.
kranthi
@Kranthi: since your sample code doesn't have any classes on the li tags, it's hard to say exactly what you need to do. How are the classes determined (meaning, are they all the same class, or different based on depth or something)?
patmortech
yes,they are different and assigned based on the depth
kranthi
See my update to see if that's what you are looking for.
patmortech
Thanks @patmortech,I need to assign the classes based on depth but not exactly like your update.May be you were giving an example.Please see the update in my original question.With the code in update of my original question I am able to get the desired outcome(see updated unorderedlist).But the update I made looks pretty bad.Can u suggest any improvements on that please?
kranthi
A: 

You could also have used asp:Repeater which is useful for stuff like this (tables, lists, etc.).

Or you could get with the future and stop wasting server resources to render HTML...

Instead, push the list data to the client as XML or JSON and then use jQuery or JS/XSLT to render the HTML from the data, thus leveraging client resources for the presentation, and taking some load off of the server (and the network, because once the server renders all that stuff it has to send the fully-rendered HTML in the response, plus any ViewState (if you're using it)).

Ray Moro