我如何计数循环在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>
您可以在视图中执行以下色情内容:
@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>
}