如何在C# MVC3 Razor中使用@foreach列表交替显示项目?

46
在MVC3中,当使用Razor视图引擎时,如何在@foreach列表上创建交替行颜色?
@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>
}

2
一年过去了,由于有如此多的浏览量,我不得不更改接受的答案。CSS是正确的方法,而不是代码。 - JK.
6
@trebormf的回答依赖于JavaScript。得票最高的答案(@Kirk Woll)将可以完成相同的任务,但不需要依赖JavaScript,这样可以兼容更多客户端,更轻量级和更快速的渲染 - 在我看来是“更正确”的。最初选择的答案确实使用了CSS。它是嵌入式CSS,但无论如何,还是使用了CSS。您可以将其更改为设置类名或其他方式,而不是嵌入式CSS。 - BenSwayne
2
CSS是应用样式的正确方式。然而,使用JQuery在DOM中呈现表格,然后进行更改仍然是代码:只不过不是你的代码。我怀疑如果您对页面生成进行性能计时,您会发现基于服务器的方法更快,并且不依赖JS。 - Quango
14个回答

56

假设您不想使用CSS(即:nth-child(odd)),则可以选择以下方法之一:

  • 使用普通的for循环:

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

  • @foreach (var item in Model.Select((x, i) => new { Data = x, Index = i }))
    {
        ...
    }
    
    无论哪种方式,您都可以访问当前索引,然后可以使用i % 2 == 1作为背景颜色的条件。类似于: ```html

    {{item}}

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

接受了近一年后,我改变了主意 - 在代码中执行纯UI样式任务是不正确的。CSS才是正确的方法,我接受了trebormf的答案。 - JK.
22
@JK.,出于好奇,你是否忽略了我回答中的第一句话? - Kirk Woll

42

CSS主要用于更改样式而非内容,这样可以节省服务器的工作量:在客户端完成操作。

因为您使用的是Razor,您可以使用JQuery。以下是我在项目中的做法:

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

2
+1 这实际上是正确的方法。我现在用它来制作任何交替项表格。除了我使用 .addClass() 而不是 .css()。已将接受的答案更改为此答案。 - JK.
谢谢,JK。即使你已经接受了一个答案,我还是冒险在3个月后回答了你的问题。我很感激。 - trebormf
19
既然您正在使用 Razor,您可以使用 jQuery。-这是什么意思?它们彼此独立。 - David East
3
这并不是我说话的最佳措辞。MVC3/Razor项目模板中包括jQuery。你是对的,它们并没有必然联系。 - trebormf

25

使用 ASP.NET MVC 3 和新的 @helper 语法,有一种更加简洁的处理方式。

首先添加以下 @helper 方法:

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

然后只需在您的<TR>元素中添加对该辅助程序的调用即可。

@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>
}

做得好!有一个小的格式错误,应该是<tr @AlternateBackground("Red")>。如果没有'@',它将不能正常工作。 - Rondel
这对处理HTML电子邮件帮助了我很大的忙。正如你所知道的,某些电子邮件(如em、GMail)会剥离CSS <style>标记,而其他电子邮件(如Outlook)则会搞乱CSS。我使用CSS的nth东西设置了漂亮的斑马条纹,但被HTML电子邮件“兽”猛击了。使用MVC3,这极大地帮助我将条纹放回长表中。耶!只需在每个<tr>添加@(糟糕?)。 - REMESQ
多么出色的答案。现在我不再需要一个表格了,我将它用于面板。 - user2537701

22

你可以使用纯CSS实现:

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

这是我认为更优雅的解决方案。谢谢! - Vinzz
是的,我同意。对我来说,这是最好的解决方案。谢谢。 - sammydc
+1,优雅的语法。但是,在使用CSS进行任何花哨的操作时,您应该始终提及浏览器支持。在这种情况下,IE 9之前的版本不支持 - Patrick M

9
这个怎么样?
@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>

它是IEnumerable,所以@for无法工作,而<tr @(i % 2 != 0 ? class="odd" : "")>也有问题。 - JK.
第二行代码可能更好写成:<tr class="@(i%2 != 0 ? "odd" : null)" > - Quango
@Quango:是的,在 MVC4+ 中附带的 Razor 版本中,这是更好的方法(不过在 MVC3 的 Razor 引擎中会留下 class=""(或者应该是 class=null?),这有点不太规范)。 - Dave Ward

5
@{  
    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++;
    }
}

3

原文:http://15daysofjquery.com/table-striping-made-easy/5/ 作者:杰克·伯恩 jQuery 简单实现斑马线表格

=============== JavaScript ===================

$(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">

我喜欢这种动态附加类值的方式。 - Diin

2

谢谢,我也会尝试一下 - @anurse,因为您是Razor答案最权威的来源 :) - JK.

1

这是一篇旧帖,但是没有一个答案涵盖了这种方法,所以我来补充一下。

由于您正在使用MVC Razor,利用@helper函数是最简单、最清晰、最好的方法。

在您项目的App_Code文件夹中添加新项目或修改现有的CustomeHelpers.cshtml文件,加入以下代码:

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

然后在您的视图中,foreach循环应该如下所示:
@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>
}

你可以传递一个颜色标识符,如“#ECEDEE”或命名为“蓝色”。
这样,您只需添加@Helper函数一次,并且它会在整个应用程序中传播,可以通过引用@CustomHelpers函数在每个视图上根据需要调用。

1
你可以在 foreach() 的外部设置变量 odd
@{
    var odd = false;
}

在你的foreach循环中,你需要改变它的值,并在一个if条件语句中使用它来设置交替类。
@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>
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接