我如何计数循环在mvc3 @foreach

本文关键字:mvc3 @foreach 循环 何计数 | 更新日期: 2023-09-27 18:14:49

如何在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>

我如何计数循环在mvc3 @foreach

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

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

现在我们开始认真对待这件事了

我首先想到的是Phil Haack更好的foreach循环

使用它可以获得一个索引,并且可以像

那样使用它
<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>" : ""))

这样可以。

@{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.

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

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

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