简单的If/Else Razor语法

45

我正在尝试在foreach中使用以下代码进行简单的If / Else:

@{
var count = 0;
foreach (var item in Model)
{
    if (count++ % 2 == 0)
    {
        @:<tr class="alt-row">
    } else { 
        @:<tr>
    }
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.Truncate(item.Details, 75)
        </td>
        <td>
            <img src="@Url.Content("~/Content/Images/Projects/")@item.Images.Where(i => i.IsMain == true).Select(i => i.Name).Single()" 
                alt="@item.Images.Where(i => i.IsMain == true).Select(i => i.AltText).Single()" class="thumb" />
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProjectId }) |
            @Html.ActionLink("Details", "Details", new { id = item.ProjectId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProjectId })
        </td>
    </tr>
}
}

我遇到了一个解析错误: "遇到了没有匹配开始标签的结束标签"tr"。您的起始/结束标记是否正确平衡?". 看起来if语句不起作用。

4个回答

50

只需使用此代码作为结束标签:

  @:</tr>

并且保留你的if / else语句不变。

似乎if语句不起作用。

它是正常工作的。在这里,您正在使用两个语言空间,因此似乎只能适当地不要跨越边界分裂开/闭标签。


1
谢谢。我尝试了@DJQuimby的解决方案,它有点起作用,但是else不再以蓝色突出显示,并且我收到了这个错误:“代码块缺少一个闭合“}”字符。确保此块中所有“{”字符都有匹配的“}”字符,并且没有任何“}”字符被解释为标记。” 不过你的解决方案有效,感谢你们两个的建议。 - Shane LeBlanc
1
@Henk Holterman 感谢您的回答。但是在Visual Studio中,如果我按下ctrl + k + D来对齐代码,它会重新格式化为 @:(</tr>移到下一行)。因此又导致了相同的错误。 - Rahul Nikate
Pahul,你有解决这个问题的方法吗? - CularBytes

13

我会选择

<tr @(if (count++ % 2 == 0){<text>class="alt-row"</text>})>

或者更好的是

<tr class="alt-row@(count++ % 2)">
这将给你类似这样的行。
<tr class="alt-row0">
<tr class="alt-row1">
<tr class="alt-row0">
<tr class="alt-row1">

你为什么在那里加了一个<text>标签? - Akira Yamamoto
2
抱歉,我找到原因了:https://weblogs.asp.net/scottgu/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax - Akira Yamamoto
太好了!只是想补充一下,外面的括号导致 VS 指示 if 是一个“无效表达式项”。所以我把它们去掉了:<div class="row @if(cond){<text>...</text>}">,然后它就可以工作了。 - CPHPython

7

也许有点离题,但对于现代浏览器(IE9 及以上版本),您可以使用 CSS 奇偶选择器来实现您想要的效果。

tr:nth-child(even) { /* your alt-row stuff */}
tr:nth-child(odd) { /* the other rows */ }

或者

tr { /* all table rows */ }
tr:nth-child(even) { /* your alt-row stuff */}

2
为了消除if/else的笨拙,您可以使用using块:
@{
    var count = 0;
    foreach (var item in Model)
    {
        using(Html.TableRow(new { @class = (count++ % 2 == 0) ? "alt-row" : "" }))
        {
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.Truncate(item.Details, 75)
            </td>
            <td>
                <img src="@Url.Content("~/Content/Images/Projects/")@item.Images.Where(i => i.IsMain == true).Select(i => i.Name).Single()" 
                    alt="@item.Images.Where(i => i.IsMain == true).Select(i => i.AltText).Single()" class="thumb" />
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ProjectId }) |
                @Html.ActionLink("Details", "Details", new { id = item.ProjectId }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ProjectId })
            </td>
        }
    }
}

可重复使用的元素使添加属性更加容易:

//Block is take from http://www.codeducky.org/razor-trick-using-block/
public class TableRow : Block
{
    private object _htmlAttributes;
    private TagBuilder _tr;

    public TableRow(HtmlHelper htmlHelper, object htmlAttributes) : base(htmlHelper)
    {
        _htmlAttributes = htmlAttributes;
    }

    public override void BeginBlock()
    {
        _tr = new TagBuilder("tr");
        _tr.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(_htmlAttributes));
        this.HtmlHelper.ViewContext.Writer.Write(_tr.ToString(TagRenderMode.StartTag));
    }

    protected override void EndBlock()
    {
        this.HtmlHelper.ViewContext.Writer.Write(_tr.ToString(TagRenderMode.EndTag));
    }
}

帮助方法,使razor语法更清晰:

public static TableRow TableRow(this HtmlHelper self, object htmlAttributes)
{
    var tableRow = new TableRow(self, htmlAttributes);
    tableRow.BeginBlock();
    return tableRow;
}

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