How can I create a row for every 3rd column in Razor mvc5?

I am currently trying to add a new row for each 3rd column with razor. However, with the current code, only the first three columns get wrapped in a row, and the rest get skipped. I have been looking around for a fix, but none of it seems to work with my code. Does anyone have a solution for this?

@model IEnumerable<Byporten.createpost>
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_LayoutClient.cshtml";
}

<div class="container">

    @{
        var itemCount = 0;
    }

    @while (itemCount < 3)
    {
        foreach (var item in Model.Reverse().Take(9))
        {
            if(itemCount == 0 )
            {
                @:<div class="row">
            }

            <div class="col-lg-4 col-md-6 col-sm-6">
                <div class="image-section">
                    <img src="~/images/uploads/@Html.DisplayFor(modelItem => item.ImageURL)"/>
                </div>
                <div class="title-section">
                    <h5><span class="fa fa-pencil"></span> @Html.DisplayFor(modelItem => item.Title)</h5>
                    @Html.ActionLink("Les mer", "viewArticle", new { id = item.Id })
                </div>
            </div>

            itemCount++;

            if ((itemCount % 3) == 0)
            {
                @:</div>
            }

        }
        
    }
    @{itemCount = 0;}
</div>

Upvotes: 3

Views: 7348

Answers (4)

Jacques
Jacques

Reputation: 7135

None of these worked for me, but the following did:

@foreach (var item in Model.Items)
{
    var itemCount = 0;
    foreach (var listItem in ((ListViewModel)item).ListItemViewModel.Items)
    {
        if (itemCount == 0)
        {
            @:<div class="row">
        }

        <div class="col-md-4">
            <a href="#" data-sf-role="toggleLink" class="organogram-title"><span class="organogram-outter-ring"></span>@listItem.Fields.Title</a>
            <div style="display:none;" class="sf-list-content">
                @Html.Raw(listItem.Fields.Content)
            </div>
            <div class="organogram-outter-ring"></div>
        </div>

        if (itemCount == 2)
        {
            itemCount = 0;
            @:</div>
        }
        else
        {
            itemCount++;
        }
    }
}

Upvotes: 2

JasonWilczak
JasonWilczak

Reputation: 2403

So, I know I am a little late to the game and there is an accepted answer, however, I want to add my rendition because it requires no duplicate if statements and no code compilation squigglies.

My approach uses an inner for loop based on the number of columns you want to have before creating a new row:

<table>
        <thead>
                <tr>
                     <td><b>My List Data:</b></td>
                </tr>
        </thead>
        <tbody>
                @{
                   var items = Model.MyList;
                   const int colCount = 2;
                }
                @for (var i = 0; i < items.Count(); i += colCount)
                {
                  <tr>
                        @for (var c = 0; c < colCount && i + c < items.Count(); c++)
                        {
                            <td>@(items[i + c].Display):</td>
                        }
                  </tr>
                }
        </tbody>
</table>

The premise is to determine what your column count is, that is show above using const int colCount =2;

Then, loop, using a for loop, on your list but instead of incrementing by 1, as is traditional, increment by your colCount value.

Then, have your row tag. This means a row will be created every n+colCount items.

Within that row tag, have another for loop that increments by 1 until you either reach your colCount OR your parent iterator plus your colCount iterator equals or exceeds the total items in your list.

Within that for loop, simply create a cell that is at the index of i (outer iterator) + c (colCount) iterator.

This gives you a nice left to right, top to bottom table structure from a flat list without extra if statements and compilation warnings.

Upvotes: 0

Electrionics
Electrionics

Reputation: 6772

Use Html.Raw() method to avoid compilation problems with conditional closing tag, and temp variable insertRow to avoid repeating in row condition:

<div class="container">

@{
    var itemCount = 0;
}

@{
    foreach (var item in Model.Reverse().Take(9))
    {
        var insertRow = itemCount % 3 == 0;

        if(insertRow)
        {
            @Html.Raw("<div class="row">")
        }

        <div class="col-lg-4 col-md-6 col-sm-6">
            <div class="image-section">
                <img src="~/images/uploads/@Html.DisplayFor(modelItem => item.ImageURL)"/>
            </div>
            <div class="title-section">
                <h5><span class="fa fa-pencil"></span> @Html.DisplayFor(modelItem => item.Title)</h5>
                @Html.ActionLink("Les mer", "viewArticle", new { id = item.Id })
            </div>
        </div>

        if (insertRow)
        {
            @Html.Raw("</div>")
        }

        itemCount++;
    }
}
</div>

And also while (itemCount < 3) loop is look strange and unnecessary for your task.

Upvotes: 0

Denat Hoxha
Denat Hoxha

Reputation: 945

It's going to result in invalid markup because itemCount == 0 will be true only once. Replace if (itemCount == 0) with if (itemCount % 3 == 0 || itemCount % 3 == 3).

I would also get rid of the while loop and the itemCount reset at the bottom.

Upvotes: 1

Related Questions