How can i close <tr>
and open <tr>
after 3 loop iterations? I have MVC 3 in .NET 4.0. How can I count loop iterations in MVC 3?
Current Code:
@foreach (var articleOnFirstPage in Model.ArticlesOnFirstSite)
{
<tr>
<td><div class="productsFrame"></div></td>
</tr>
}
I want to get this:
<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>
Working of C# foreach loop The in keyword used along with foreach loop is used to iterate over the iterable-item. The in keyword selects an item from the iterable-item on each iteration and store it in the variable element. On first iteration, the first item of iterable-item is stored in element.
The foreach loop iterate only in forward direction. Performance wise foreach loop takes much time as compared with for loop. Because internally it uses extra memory space as well as. The foreach loop use GetEnumarator () method of the IEnumerable interface. So, the foreach loop can be used with any class that has implemented the interface.
The foreach loop use GetEnumarator () method of the IEnumerable interface. So, the foreach loop can be used with any class that has implemented the interface. Exit the foreach loop by using break, return, Goto and throw. The following example demonstrates the foreach loop on a dictionary collection.
The number of times the foreach loop will execute is equal to the number of elements in the array or collection. Here is an example of iterating through an array using the for loop: The same task can be done using the foreach loop. When we run the both program, the output will be:
You could perform the following pornography in your view:
@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>
or simply use view models and do the grouping in your controller action which obviously is what I would recommend you. The sole fact that you need to do this means that your view model is not adapted to your view's requirements which is to group results by 3. So adapt it. Don't pass IEnumerable<Foo>
to your view. Pass IEnumerable<MyViewModel>
where obviously MyViewModel will contain the necessary grouping so that in your views you could simply loop or since I hate writing for and foreach loops in views simply use display templates. They will take care of everything and your view will simply look like this:
<table>
@HtmlDisplayForModel()
</table>
Looks better than the initial pornography isn't it?
As requested in the comments section here's how I would implement this using view models.
As always in an ASP.NET MVC application you start by defining the view models that will reflect the requirements of your view (which I repeat are: show a table with 3 columns):
public class ItemViewModel
{
public string Title { get; set; }
}
public class MyViewModel
{
public IEnumerable<ItemViewModel> Items { get; set; }
}
then you move on to the controller that will fill and pass this view model to the view:
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);
}
}
and finally you write the corresponding view (~/Views/Home/Index.cshtml
):
@model IEnumerable<MyViewModel>
<table>
@Html.DisplayForModel()
</table>
and the ~/Views/Home/DisplateTemplates/MyViewModel.cshtml
display template:
@model MyViewModel
<tr>
@Html.DisplayFor(x => x.Items)
</tr>
and finally the corresponding ~/Views/Home/DisplateTemplates/ItemViewModel.cshtml
display template:
@model ItemViewModel
<td>@Html.DisplayFor(x => x.Title)</td>
and that's pretty much it. Simple, clean, following good practices and conventions.
Obviously to bring this a step further you would introduce AutoMapper to perform the actual mapping between your domain models and view models and you will end up with a very elegant solution that will look like this:
public ActionResult Index()
{
IEnumerable<DomainModel> data = ...
var viewModel = Mapper.Map<IEnumerable<DomainModel>, IEnumerable<MyViewModel>>(data);
return View(viewModel);
}
or a step further:
[AutoMap(typeof(IEnumerable<DomainModel>), typeof(IEnumerable<MyViewModel>))]
public ActionResult Index()
{
IEnumerable<DomainModel> data = ...
return View(data);
}
Now we are starting to get into serious business.
The first thing that comes to mind is Phil Haack's better foreach loop
Using it you gain an index and can use it like
<ol>
@Model.Each(@<li>Item @item.Index of @(Model.Count() - 1): @item.Item.Title</li>)
</ol>
What you're specifically looking for should be something like:
@Model.ArticlesOnFirstSite.Each(@<td><div class="productsFrame"></div></td>@(@item.Index % 3 == 0 ? "</tr><tr>" : ""))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With