C# MVC3 Razor alternating items in a @foreach list?

In MVC3, how do you create alternating row colors on a @foreach list when using the Razor view engine?

@foreach (var item in Model) {    
    <tr>
        <td>@item.DisplayName</td>
        <td>@item.Currency</td>
        <td>@String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
        <td>@String.Format("{0:g}", item.CreatedBy)</td>
        <td>@Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
    </tr>
}

Answers


This is what CSS is for (changing style rather than content). Save the server the effort: Do it on the client.

Since you're using Razor, you can use JQuery. Here's how I do it in my projects:

$(document).ready(function () {
    $("table > tbody tr:odd").css("background-color", "#F7F7F7");
}

Assuming you would rather not use CSS (i.e. :nth-child(odd)) you can either:

  • use a normal for loop:

    @for (int i = 0; i < Model.Count; i++)
    {
        ...
    }
    
  • use .Select:

    @foreach (var item in Model.Select((x, i) => new { Data = x, Index = i }))
    {
        ...
    }
    

Either way, you'd have access to the current index and could then use i % 2 == 1 as the condition for your background-color. Something like:

<tr style="background-color:@(i % 2 == 1 ? "red" : "white")">...</tr>

With ASP.NET MVC 3 and the new @helper syntax, there is a neater way to handle this.

First add this @helper method:

@helper AlternateBackground(string color) {
    if (ViewBag.count == null) { ViewBag.count = 0; }
    <text>style="background-color:@(ViewBag.count % 2 == 1 ? color : "none")"</text>
    ViewBag.count++;
}

Then just add the call to the helper in your <TR> element

@foreach (var item in Model) {    
    <tr @AlternateBackground("Red")>
        <td>@item.DisplayName</td>
        <td>@item.Currency</td>
        <td>@String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
        <td>@String.Format("{0:g}", item.CreatedBy)</td>
        <td>@Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
    </tr>
}

You could always do it in pure css using:

TABLE.test tr:nth-child(even)
{
    background-color: #EFEFEF;
}

How about something like this?

@for (int i = 0; i < Model.length; i++) {
  <tr @(i % 2 != 0 ? class="odd" : "")>
    <td>@Model[i].DisplayName</td>
    <td>@Model[i].Currency</td>
    <td>@String.Format("{0:dd/MM/yyyy}", Model[i].CreatedOn)</td>
    <td>@String.Format("{0:g}", Model[i].CreatedBy)</td>
    <td>@Html.ActionLink("Edit", "Edit", new { id = Model[i].Id })</td>
  </tr>

@{  
    int i = 0;
    foreach (Account acct in Model)
    {
        <div class="row @(i%2==0?"even":"odd")">     
            <a href="/Account/Details/@acct.id">@acct.name</a>
        </div>
        i++;
    }
}

Original: http://15daysofjquery.com/table-striping-made-easy/5/ Author: Jack Born jQuery Zebra_Striping_Made_Easy

=============== Java script ===================

$(document).ready(function () {
          $('.stripeMe tr:even').addClass('alt');

          $('.stripeMe tr').hover(
            function () {
                $(this).addClass("highlight");
              },
             function () {
                $(this).removeClass("highlight");
              });
      });

================= css =================

tr.alt td {
background-color : #F7F7F7;
}
tr.highlight td {
background-color : #bcd4ec;
}

=============== HTML ===============

<table class="stripeMe">

There isn't much documentation on it, but the Loop Helper (http://nuget.org/Packages/Packages/Details/Loop-Helper-for-WebMatrix-0-1) gives you support for detecting Even/Odd/etc. items.


An old post, but none of the answers covered this approach, so I will.

Since you are using MVC Razor utilizing the @helper function is the simplest, cleanest and best approach.

In the App_Code folder of your project add new item or modify your existing CustomeHelpers.cshtml file with the following code:

@helper AlternateBackground(string color, Int32 iViewBagCount) {
    if (iViewBagCount == null) { iViewBagCount = 0; }
    <text>style="background-color:@(iViewBagCount % 2 == 1 ? color : "none")"</text>
    iViewBagCount++;
}

Then on your view your foreach loop would look like this:

@foreach (var item in Model) {    
    <tr @CustomHelpers.AlternateBackground("#ECEDEE", Model.Count())>
        <td>@item.DisplayName</td>
        <td>@item.Currency</td>
        <td>@String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
        <td>@String.Format("{0:g}", item.CreatedBy)</td>
        <td>@Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
    </tr>
}

You can pass a color identifier like "#ECEDEE" or the named color "Blue".

This way you only have to add the @Helper function once and it propagates throughout your application and it can be called on each view as needed by referencing the @CustomHelpers function.


what about using the jQuery DataTable plugin. i used it on an MVC2 application i developed.

http://www.datatables.net/


A solution i use to support IE8 (corporate browser, not by choice) was to combine the_lotus's solution with a jquery solution

Since IE8 doesnt support nth-child() use this css

.tableclass tr.even{
    background:#E6EDF5;
}

And use jQuery to do this:

$(document).ready(function() {
    $(".table tr:nth-child(even)").addClass("even");
});

You could let the framework decide how best to render it, presumably using a bit of browser detection logic and whatever other goodness it has built-in, something like the following, and get on with your life.

:-)

My point being that with this approach the WebGrid will control the alternating grid colors using the best technology it can (best that it is designed to use, at least) for the detected browser. It might not use "nth" CSS syntax, but that might not work for all of your intended audience, anyway, so you'd have to detect the browser and emit different content on your own. Of course everybody should be using a CSS 3.x-compliant browser by now, but mileage varies.

@myWebGrid.GetHtml
    (
    tableStyle: "some-style",
    headerStyle: "some-head-style",
    alternatingRowStyle: "some-fancy-alt-row-style",
    etc ...
    )

The System.Web.Helpers.WebGrid's GetHtml method signature looks like this here:

public IHtmlString GetHtml
    (
    string tableStyle = null,
    string headerStyle = null,
    string footerStyle = null,
    string rowStyle = null,
    string alternatingRowStyle = null,
    string selectedRowStyle = null,
    string caption = null,
    bool displayHeader = true,
    bool fillEmptyRows = false,
    string emptyRowCellValue = null,
    IEnumerable<WebGridColumn> columns = null,
    IEnumerable<string> exclusions = null,
    WebGridPagerModes mode = WebGridPagerModes.Numeric | WebGridPagerModes.NextPrevious,
    string firstText = null,
    string previousText = null,
    string nextText = null,
    string lastText = null,
    int numericLinksCount = 5,
    object htmlAttributes = null
    );

What you can do is to set a variable odd outside of the foreach()

@{
    var odd = false;
}

And then, inside your foreach loop, you'd change the value of it and then use it in an if condition to set the alternating classes.

@foreach (var item in Model) {
    odd = !odd;

    <tr class="@(odd ? "odd" : "even")">
        <td>@item.DisplayName</td>
        <td>@item.Currency</td>
        <td>@String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
        <td>@String.Format("{0:g}", item.CreatedBy)</td>
        <td>@Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
    </tr>
}

@helper Prop(List prop) { foreach (var p in prop) { p } }

format: @Prop(@item.Prop)


Need Your Help

NSAttributedString initWithHTML incorrect character encoding?

cocoa nsattributedstring

-[NSMutableAttributedString initWithHTML:documentAttributes:] seems to mangle special characters:

Horizontally mirror a SKSpriteNode texture

objective-c swift image ios7 sprite-kit

I'm developing an iOS7 game with the new API called Sprite Kit. I'd like to horizontally rotated a SKSpriteNode image/texture. I've tried it by first mirroring the image, then creating a SKTexture ...