Home > Mobile >  How to group a C# list when being displayed in html page
How to group a C# list when being displayed in html page

Time:12-07

string flowerList = string.Empty;
foreach (var flower in Plants.Where(x => x.Status == PlantStatus.Active))
{
    flowerList = string.IsNullOrWhiteSpace(flowerList)
                 ? "<li>"   flower.Colour   " "   flower.Priority   " "   flower.Category   "</li>"
                 : flowerList   "<li>"   flower.Colour   " "   flower.Priority   " "   flower.Category  "</li>" ;
}

I have the above code to display a C# list data data in a html page. How can i group my flowerList html out put by flower.Category.

For each Category, I would wish to have flower.Category as the group header and then under it list the related records.

CodePudding user response:

The code is already using LINQ. Grouping in LINQ is performed by the GroupBy operator. It's not a good idea to put the query in the foreach clause though, even for simple queries. Modifying it becomes a lot harder.

This snippet groups by category and then generates the HTML string. Instead of concatenating strings though it uses a StringBuilder to avoid creating temporary strings.

var categories=Plants.Where(x => x.Status == PlantStatus.Active)
                 .GroupBy(x=>x.Category);

var builder=new StringBuilder();
foreach(var category n categories)
{
    builder.AppendFormat("<div>\n<h1>{0}</h1>\n", category.Key);
    foreach(var flower in category)
    {
        builder.AppendFormat("<li>{0} {1}</li>\n", 
                           flower.Colour, 
                           flower.Priority);
    }
    builder.AppendLine("</div>");
}

var html=builder.ToString();

Template Engines

Generating strings like this works only for simple HTML though. Even this code is becoming hard to maintain. In such cases it's better to use a template engine like Visual Studio's T4 or the more modern Scriban or Handlebars.NET.

The following example uses Scriban

var template = Template.Parse(@"
  <H1>Flowers by Category</H1>
  {{ for category in Categories }}
    <div>
       <h2>{{ category.key }}</h2>
       <ul>
       {{ for flower in category }}
           <li>{{ flower.Colour }} {{ flower.Priority }}</li>
       {{ end }} 
       </ul>
    </div>
  {{ end }}
");

var html = template.Render(new { Categories = categories });

It's now a lot easier to understand what the output will look like, edit the template and find any errors

CodePudding user response:

Here is one possible way to group the output by flower.Category:

string flowerList = string.Empty;

// Group the flowers by category
var flowerGroups = Plants
    .Where(x => x.Status == PlantStatus.Active)
    .GroupBy(x => x.Category);

// Iterate over the groups and create the HTML output
foreach (var group in flowerGroups)
{
    // Create the header for the group
    flowerList  = "<h3>"   group.Key   "</h3>";

    // Create a list of flowers in the group
    flowerList  = "<ul>";
    foreach (var flower in group)
    {
        flowerList  = "<li>"   flower.Colour   " "   flower.Priority   " "   flower.Category   "</li>";
    }
    flowerList  = "</ul>";
}

This code will first group the flowers by flower.Category, then iterate over the groups and create a heading for each group followed by a list of flowers in that group. The final result will be a string containing the HTML output.

CodePudding user response:

var categories=Plants.Where(x => x.Status == PlantStatus.Active) .GroupBy(x=>x.Category);

var builder=new StringBuilder("

    "); foreach(var plants in categories) { foreach(var plant in plants) { builder.AppendFormat("
  • {0} {1} {2}
  • \n", flower.Colour, flower.Priority, flower.Category); } } builder.AppendLine("
");

var html=builder.ToString();

  • Related