3

I'm trying to apply a responsive design to my ASP.NET MVC 4 application. I want to loop my model and render 3 items per line. Each line shall be wrapped in a div. The result should look something like this:

<div class='ResponsiveWrapper'>
    <div>
        <!-- item1 -->
    </div>
    <div>
        <!-- item2 -->
    </div>
    <div>
        <!-- item3 -->
    </div>
</div>
<div class='ResponsiveWrapper'>
    <div>
        <!-- item4 -->
    ...

In order to do so, I'm trying to use ternary operators:

@{ var i = 0; }

@foreach (var item in Model)
{
    @Html.Raw(i == 0 ? Html.Encode("<div class='section group'>") : "")
    
    <div>
        //Responsive Content comes here
    </div>

    @Html.Raw(i == 2 ? Html.Encode("</div>") : "")

    @(i<3 ? i++ : i=0)
}

Now I have 2 problems:

  1. The HTML tags which the ternary operators should render come in plain text. I tried different combinations of @Html.Raw and @Html.Encode and Strings, but it nothing worked for me

  2. It seems like the last ternary operator renders the current value of the variable i. How can I prevent this?

Additional information/code explanation

The logic already works fine:

  • The i Variable is the count variable.
  • If i = 0 I first render the start <div> tag of the wrapper and than I render the current model.item
  • If i = 1 I only render the current model.item
  • If i = 2 I first render the current model.item and than the </div> end tag

Thank you

UPDATE

Both, MajoB's and Chris Pratt's approaches basically work. Since MajoB's solution was more detailed, I went with that one. However, I had to make some modifications in order to get it to work:

  1. At the controller, I had to assure, that an IList is being returned, rather than an IEnumerable

     public ActionResult Index()
     {
         return View(db.leModel.ToList());
     }
    
  2. In the View, I had to change the signature (like 1, IList instead of IEnumerable)

     @model IList<leProject.Models.leModel>
    
  3. Various modifications in the Razor code (otherwise it would throw me exceptions)

Final code:

<div class="ResponsiveWrapper">
@for (var i = 0; i < Model.Count; i++)
{
    // the lambda expression modelItem => item.leProperty did not work for some reason. So I had to replace the item with Model[i], which means, the following line is not necessary
    { var item = Model[i]; }

    <div>
        @Html.DisplayFor(modelItem => Model[i].leProperty)
    </div>

    if ((i + 1) % 3 == 0 || i == (Model.Count - 1))
    {
        @:</div> 
        if (Model.Count + 1 - i >= 3)
        {
            @:<div class="ResponsiveWrapper">
        }
    }
}

Thank you guys :)

1
  • @(stuff) tells Razor to print the output. try @{stuff} instead :-) Commented Nov 20, 2015 at 7:08

2 Answers 2

2

Solution without the wrapper div:

@for(var i = 0; i < Model.Count; i++)
{
   @{ var item = Model[i]; }      

   <div style="float:left;">
       <!-- item1 -->
   </div>

   @if((i+1) % 3 == 0)
   {
    <div style="clear:both;"></div>
   }
}

Solution with wrapper:

<div class="ResponsiveWrapper">
@for(var i = 0; i < Model.Count; i++)
{
   @{ var item = Model[i]; }           


   <div>
       <!-- item1 -->
   </div>

   @if((i+1) % 3 == 0 || i == (Model.Count-1)) // in case you have for example 7 items in your list
   {
    @:</div> <!-- end ResponsiveWrapper -->
    @if (i != Model.Count-1)
    {
    @:<div class='ResponsiveWrapper'>
    }
   }      
}
Sign up to request clarification or add additional context in comments.

3 Comments

since my Model is a IEnumerable I get an exception "cannot apply indexing with to an expression of type ...ienumerable" how can I fix that?
You can change your model to list Model.ToList() or use the foreach approach from your question.
had to make a few modification, in order to get it to work. I'll update my questions with the tasks I did
2

Here's the usual way to handle this:

<div class="ResponsiveWrapper">
@for (var i = 0; i < Model.Count; i++)
{
    <div>
        <!-- item -->
    </div>

    @if ((i + 1) % 3 == 0)
    {
        @:</div><div class="ResponsiveWrapper">
    }
}
</div>

Every third item, the wrapper div is closed and opened again. The @: prevents Razor from trying to parse this line, so it doesn't throw erroneous syntax errors.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.