如何在MVC3中使用Razor混合HTML和C#代码?

31

我正在尝试显示一个项目列表,它应该可切换类以进行样式设置。我的想法是创建一个循环来遍历模型中的所有myObj

我尝试了以下代码,但它不起作用(因为我做错了)。

@{ int i = 2;
   foreach(var myObj in Model)
   {
        if (i % 2 == 0)
        {
            <div class="class1">
        }
        else
        {
            <div class="class2">
        }
        Html.Partial(...);
        </div>
         i += 1;
   }     
}
这应该怎样正确完成? 更新
我也尝试过以下代码,虽然能编译通过,但其中没有呈现任何HTML代码(而我确定Model中有对象)。
@{ int i = 2;
   foreach(var myObj in Model)
   {
        if (i % 2 == 0)
        {
            @:<div class="class1">
        }
        else
        {
            @:<div class="class2">
        }
        Html.Partial(...);
        @:</div>

        i += 1;
   }

}

这是被调用的部分类

<div class="class">
    <div class="class2">
        @if (string.IsNullOrEmpty(var))
        {
            @var2
        }
        else
        {
            @var
        }
    </div>
    <div class="class3">
        @var3
    </div>
</div>
<div class="class4">
    <p>var4</p>
    <ul class="class5">
        <li>element1</li>
        <li>element2</li>
    </ul>
</div>

抱歉,我无法发布实际名称和变量。


你能具体说明一下它为什么不起作用吗?你有输出吗?你有异常吗? - Chris Shain
更新:我们能看到部分视图和调用它的代码吗? - Khepri
4个回答

27

让我们从改进你的代码开始。

  • Improvement step 1:

    @foreach(var myObj in Model.Select((model, index) => new { model, index }))
    {
        <div class="class@(myObj.index % 2 == 0 ? "1" : "2")">
            @Html.Partial("_Foo", myObj.model)
        </div>
    }
    
  • Improvement Step 2 (using a custom HTML helper for the class):

    @foreach(var myObj in Model.Select((model, index) => new { model, index }))
    {
        <div class="@Html.MyClass(myObj.index)">
            @Html.Partial("_Foo", myObj.model)
        </div>
    }
    

    where MyClass is defined like this:

    public static string MyClass(this HtmlHelper html, int index)
    {
        return (index % 2 == 0) ? "class1" : "class2";
    }
    
  • Improvement step 3 which is the state of the art (using Templated Razor Delegates):

    @Model.List(
        @<div class="@item.MyClass">
            @Html.Partial("_Foo", @item.Model)
        </div>
    )
    

    where the List extension method looks like this:

    public class ModelHolder<T>
    {
        public T Model { get; set; }
        public string MyClass { get; set; }
    }
    
    public static class RazorExtensions
    {
        public static HelperResult List<T>(
            this IEnumerable<T> items,
            Func<ModelHolder<T>, HelperResult> template
        )
        {
            return new HelperResult(writer =>
            {
                foreach (var item in items.Select((model, index) => new { model, index }))
                {
                    var myClass = item.index % 2 == 0 ? "class1" : "class2";
                    template(new ModelHolder<T> { Model = item.model, MyClass = myClass }).WriteTo(writer);
                }
            });
        }
    }
    

我支持改进方案3,它比原始的foreach循环更好,更简洁。


2
我尝试了改进1,它起作用了。供以后参考,我没有测试其他的。 - PedroC88
3
我认为回顾并咨询旧问题总是有益的……当时这个答案看起来很复杂,我甚至没有尝试其他改进,现在一切都显得如此明显……再次感谢Darin,这是一个非常好的答案。 - PedroC88

19

为了防止Razor尝试解析非格式良好的标签,您需要在这些行前面加上@:前缀。
详情


8

您可以确定某些模型中存在对象——但不是您的模型:)下面的示例代码直接从您的代码派生而来,运行得非常好:


@{ int i = 2;
   string[] list = new string[] {"a","b","c","d"};
   foreach(var myObj in list)
   {
        if (i % 2 == 0){
            @:<div class="class1">
        }
        else
        {
            @:<div class="class2">
        }
        //Html.Partial(...);
        @:</div>
         i += 1;
   }     
}



0

你需要编写@Html.Partial(...)来将结果呈现到页面上。

调用Html.Partial会返回一个带有部分视图的HelperResult,但实际上并不会呈现它。


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