Rendering an unordered list using asp.net
Asked Answered
V

4

9

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.

Valverde answered 26/2, 2010 at 15:53 Comment(0)
P
4

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.

Posturize answered 26/2, 2010 at 17:14 Comment(9)
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.Startle
Hi Chris,why would you not recommend the above method?Valverde
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.Posturize
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.Startle
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.Startle
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).Posturize
@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 #2362061 ,where I've posted another question regarding the generated unorderedlist.Valverde
@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)?Posturize
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?Valverde
E
3

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.

Elstan answered 26/2, 2010 at 16:49 Comment(3)
The repeater control is almost deprecated by the ListView control.Startle
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?Valverde
@kranthi: For drag-and-drop and rich features you might try a 3rd-party component like Telerik telerik.com/products/aspnet-ajax/treeview.aspxLeveloff
S
2

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

Startle answered 26/2, 2010 at 16:51 Comment(0)
D
0
     void PopulateChild(int ParentId, StringBuilder output)
                {
                    var childs = GetChildren(ParentId); //get all the chilren with respect to that parent
                    if (childs.Count > 0)
                    {
//if children are there append another list to the parent node
                        output.Append("<ul>");
                        childs.ForEach(x =>
                        {
                            if (GetChildren(x.Id).Count > 0)
                            {
                                output.AppendFormat("<li><a href=\"#\">{0}</a>", x.Email);
                                output.Append("<ul>");
                                PopulateChild(x.Id, output);
                                output.Append("</li>");
                                output.Append("</ul>");

                            }
                            else
                                output.AppendFormat("<li><a href=\"#\">{0}</a></li>", x.Email);

                        });
                    }

                    output.Append("</ul>");
                }

    //call this method with the parentid 
    private void PopulateList(int CustomerId)
                {
                    StringBuilder output = new StringBuilder();
                    var row = GetCustomerDetailById(CustomerId);
                    output.Append("<ul>");
                    output.AppendFormat("<li><a href=\"#\">{0}</a>", row.Email);

                    PopulateChild(CustomerId, output);

                    output.Append("</li></ul>");

                    Literal1.Text = output.ToString();
                }
Debauchery answered 28/1, 2020 at 5:33 Comment(1)
Hello and welcome to the SO. This is a lot of code you wrote but its not too easy to understand without any comments. It would be very helpful to the other users if you appended this answer with a few sentences on how your code works and how it solves the OP's problem~Impassive

© 2022 - 2024 — McMap. All rights reserved.