我如何计算@foreach中mvc3中的循环

时间:2011-11-15 20:42:50

标签: c# asp.net-mvc-3

如何在3次循环迭代后关闭<tr>并打开<tr>?我在.NET 4.0中有MVC 3。我如何计算MVC 3中的循环迭代?

当前代码:

@foreach (var articleOnFirstPage in Model.ArticlesOnFirstSite)
{

<tr>
    <td><div class="productsFrame"></div></td>
</tr>

}

我想得到这个:

<tr>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
    </tr>
<tr>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
    </tr>
<tr>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
        <td><div class="productsFrame"></div></td>
    </tr>

4 个答案:

答案 0 :(得分:5)

首先想到的是Phil Haack的better foreach loop

使用它可以获得索引并可以像

一样使用它
<ol>
@Model.Each(@<li>Item @item.Index of @(Model.Count() - 1): @item.Item.Title</li>)
</ol>

你特别想要的是:

@Model.ArticlesOnFirstSite.Each(@<td><div class="productsFrame"></div></td>@(@item.Index % 3 == 0 ? "</tr><tr>" : ""))

答案 1 :(得分:5)

您可以在视图中执行以下色情内容:

@model IEnumerable<Foo>
<table>
@foreach (var item in from i in Model.Select((value, index) => new { value, index }) group i.value by i.index / 3 into g select g)
{
    <tr>
        @foreach (var x in item)
        {
            <td><div class="productsFrame">@x.SomeProperty</div></td>
        }
    </tr>
}
</table>

或者只是使用视图模型并在控制器操作中进行分组,这显然是我建议您使用的。您需要执行此操作的唯一事实意味着您的视图模型不适合您的视图要求,即将结果分组3.因此请对其进行调整。不要将IEnumerable<Foo>传递给您的观点。通过IEnumerable<MyViewModel>显然MyViewModel将包含必要的分组,以便在您的视图中您可以简单地循环或因为我讨厌写入和视图中的foreach循环只需使用显示模板。他们会处理所有事情,您的观点将如下所示:

<table>
    @HtmlDisplayForModel()
</table>

看起来比最初的色情内容更好吗?


根据评论部分的要求,我将如何使用视图模型实现此目的。

在ASP.NET MVC应用程序中始终,首先定义将反映视图要求的视图模型(我重复的是:显示包含3列的表):

public class ItemViewModel
{
    public string Title { get; set; }
}

public class MyViewModel
{
    public IEnumerable<ItemViewModel> Items { get; set; }
}

然后你转到控制器,它将填充并将此视图模型传递给视图:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // Obviously in a real world application the data is your domain model
        // and comes from a repository or a service layer depending on the complexity
        // of your application. I am hardcoding it here for the 
        // purposes of the demonstration
        var data = Enumerable.Range(1, 30).Select(x => new { Title = "title " + x });

        var model =
            from i in data.Select((value, index) => new { value, index })
            group i.value by i.index / 3 into g
            select new MyViewModel
            {
                Items = g.Select(x => new ItemViewModel { Title = x.Title })
            };

        return View(model);
    }
}

最后你写了相应的视图(~/Views/Home/Index.cshtml):

@model IEnumerable<MyViewModel>
<table>
    @Html.DisplayForModel()
</table>

~/Views/Home/DisplateTemplates/MyViewModel.cshtml显示模板:

@model MyViewModel
<tr>
    @Html.DisplayFor(x => x.Items)
</tr>

最后是相应的~/Views/Home/DisplateTemplates/ItemViewModel.cshtml显示模板:

@model ItemViewModel
<td>@Html.DisplayFor(x => x.Title)</td>

这就是它。简单,干净,遵循良好做法和惯例。

显然,为了更进一步,您将引入AutoMapper来执行域模型和视图模型之间的实际映射,最终将得到一个非常优雅的解决方案,如下所示:

public ActionResult Index()
{
    IEnumerable<DomainModel> data = ...
    var viewModel = Mapper.Map<IEnumerable<DomainModel>, IEnumerable<MyViewModel>>(data);
    return View(viewModel);
}

或更进一步:

[AutoMap(typeof(IEnumerable<DomainModel>), typeof(IEnumerable<MyViewModel>))]
public ActionResult Index()
{
    IEnumerable<DomainModel> data = ...
    return View(data);
}

现在我们开始认真地开展业务了。

答案 2 :(得分:3)

这样的事情可能有用。

@{int i = 0;}
@foreach (var articleOnFirstPage in Model.ArticlesOnFirstSite)
{
    @if ((i++ % 3) == 0) {
        @if (i != 1) {
            @:</tr>
        }
        @:<tr>
    }

    @:<td><div class="productsFrame"></div></td>
}

@if (i != 0) {
    @:</tr>
}

这是解决问题的有力方法。

正如其他人所建议的那样,我建议您更改方法:使用视图模型,将项目分组为3。

关于如何正确使用模型 - 视图 - 控制器模式,您可以在Web上查看。 http://msdn.microsoft.com/en-us/library/gg416514(v=vs.98).aspx是一个好的开始。

答案 3 :(得分:0)

与其他人一样,最好和最漂亮的解决方案可能是在控制器中进行分组,但这可能会完成工作:

@for (int i = 0; i < Model.ArticlesOnFirstSite.Count; i += 3)
{
    <tr>
        @foreach (Article article in Model.ArticlesOnFirstSite.Skip(i).Take(3))
        {
            <td>@article.Title</td>
        }
    </tr>
}