Building tables with WebMatrix

2019-08-14 16:36发布

问题:

I am trying to build a HTML table using WebMatrix (ASP.NET Web Pages) but am having trouble due to the way the HTML tags are opened and closed.

What I am trying to achieve is to create a table from a recordset, with three columns, and then fill in any empty columns.

This is some test code I am using to work out how to do this using WebMatrix.

<table>
@{
 int row = 0;
 int col = 0;
 for (int i = 0; i < 20; i++) //20 cells for test purposes
 {
  col++;
  if (col == 4)
  {
   col = 1;
  }
  if (col == 1)
  {
   row++;
   if (row != 1)
   {
    </tr>
   }
   <tr>
  }
  <td>@i</td>
 }
 for (int i = col; i <=3; i++)
 {
  <td>empty</td>
 }
 </tr>
}
</table>

Any suggestions for how best to accomplish this.

回答1:

Updated code sample based on the revised requirement:

@{
    var db = Database.Open("Northwind");
    var data = db.Query("SELECT * FROM Products");
    var total = data.Count();
    var counter = 1;
    var rows = total / 3;
    var spares = total % 3 > 0 ? 3 - total % 3 : 0;
    if(spares > 0){
        rows += 1;
    }
}
<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <table style="border:1px solid black">
            @for(var i = 1; i <= rows; i++){
                if( counter % 3 == 1){
                    @:<tr>
                }
                for(var cell = 1; cell <= 3 && counter <= total; cell++){
                    <td style="border:1px solid black">
                        <div>@data.ElementAt(counter-1).ProductId</div>
                        <div>@data.ElementAt(counter-1).ProductName</div>
                        <div>@data.ElementAt(counter-1).CategoryId</div>
                    </td>
                    counter++;
                }
                if(counter > total && spares > 0){
                    for(var j = 1; j <= spares; j++){
                        <td style="border:1px solid black">
                            &nbsp;
                        </td>
                    }
                }
                if(counter % 3 == 0){
                    @:</tr>
                }
            }
        </table>
    </body>
</html>

Hopefully, I've understood what you are after this time.

If you want to build the table from a recordset, why not do that? Here's an example using the Northwind database:

<table>
    @foreach(var row in data){
       <tr>
           <td>@row.ProductId</td>
           <td>@row.ProductName</td>
           <td>@row.CategoryId</td>
       </tr>
    }
</table>

Or you could use the WebGrid to do this for you.



回答2:

How about grouping your dataset before printing it? It ASP.NET MVC terms this is called view model. Unfortunately in WebMatrix you don't have a controller which could do the job of preparing this view model but you could do it in the codebehind or whatever this section of the Razor page is called:

@{
    // group the dataset by 3 elements
    var data = Enumerable.Range(0, 20).GroupBy(x => x / 3);
}

<table>
@foreach (var group in data)
{
    <tr>
        @foreach (var item in group)
        {
            <td>@item</td>
        }
        @for (int i = 0; i < 3 - group.Count(); i++)
        {
            <td>empty</td> 
        }
    </tr>
}
</table>

and if you had a dataset of complex objects and not just integers, here's how the grouping could be done:

var dataset = Enumerable.Range(0, 20).Select(x => new { Text = "item " + x });
var data = dataset
    .Select((value, index) => new { Index = index / 3, Item = value })
    .GroupBy(pair => pair.Index);

and then:

<table>
@foreach (var group in data)
{
    <tr>
        @foreach (var element in group)
        {
            <td>@element.Item.Text</td>
        }
        @for (int i = 0; i < 3 - group.Count(); i++)
        {
            <td>empty</td> 
        }
    </tr>
}
</table>

It kind of makes the code much more readable. As you can see the usage of a view model avoids you from writing ugly spaghetti code in the views.

Every-time you have some unmatched tags and you need to do integer and modulo divisions and stuff in a view you are probably doing it wrong as you didn't pick up the correct view model.