4

I have a generic list of objects that's passed to a view. Currently, each list item is displayed to the user row-by-row:

@foreach (var result in Model.SearchResults)
{
    result.Address.TownCity
    // ...
}

So each list item is displayed in its own row. Aesthetically this doesn't look the best, as there's quite a lot of white space left over.

What I want to do is something like this:

row 1 | list item 1 | list item 2

row 2 | list item 3 | list item 4

and so on.....

Is this something I have to do server-side i.e. put half of my list into another list and in the view have two foreach loops - each one filling a column, row-by-row? Or is there anyway this can be done in the view using razor?

1
  • Are you using twitter bootstrap or similar? If so, you could simply dump each item to say a div of span2 and it would simply and using responsive design, layout out the page for you based on the user's resolution: twitter.github.io/bootstrap/scaffolding.html#gridSystem Even if you're not, it's easy to do this with CSS and float:left, there is no need to make your app work harder by grouping and batching in code. Commented Apr 11, 2013 at 17:36

2 Answers 2

8

You can do this to group each set of rows into 'batches' and then loop through each item in the batch.

@{
    var batches = Model.SearchResult
        .Select((x, i) => new { x, i })
        .GroupBy(p => (p.i / 2), p => p.x);
}
@foreach(var row in batches)
{
    <span>Row @row.Key</span>
    @foreach(var item in row)
    {
        <span>| @item.Address.TownCity</span>
    }
}

Alternatively you can use this; it's simpler, though a bit less elegant

@{
    var resultArray = Model.SearchResult.ToArray(); // only necessary if SearchResult is not a list or array
}
@for(var i = 0; i < resultArray.Length; i++)
{
    var item = resultArray[i];
    if (i % 2 == 0)
    {
        <span>Row @(i / 2)</span>
    }
    <span>| @item.Address.TownCity</span>
}
Sign up to request clarification or add additional context in comments.

7 Comments

Do you not think this adds redundant code and logic to the view?
@Moby'sStuntDouble it adds additional logic to the view, but I don't see how it's redundant (where else does this logic exist?). The view is really the best place for this, because it is view logic -- concerned specifically with how to display the data. You really wouldn't want to put this in the controller.
You misunderstand where I am coming from. I am saying that you can do this in CSS. You don't need any additional code to accomplish this task. See my answer and fiddle below.
@Moby'sStuntDouble yes I like your solution, too but OP specifically asked about displayed exactly two items per row. Your solution will display as many as will fit (of course you could tweak it with .box:nth-of-type(odd) { clear: left; }). If the solution can be done only in CSS, I'd prefer to do that, but I was assuming OP needed general purpose code which would work even if you had to say, put special html around each row.
Two per row? .box{width:50%} very simple. Additional html? I fail to see what could be done with a row, that can't be done with a div. Honestly, I'm not trying to go out of my way to criticise you specifically; it's just a point of frustration when something can be done for less. The principle of minimalism in programming. I'll leave it at that. Thanks for taking the time to answer my rant.
|
4

This is very easy to do in CSS without adding additional load and complexity to your code

See this fiddle: http://jsfiddle.net/taBec/

@foreach (var result in Model.SearchResults)
{
    <div class="box">@result.Address.TownCity</div>
}

Then in CSS:

.box { width: 150px; float: left; height:25px}

Your app runs faster and your design is responsive and fluid. I hope this helps.

3 Comments

A good solution but since @p.s.w.g's answer specifically addresses my question so I chose that as the answer. Thanks.
I actually used your solution in the end.
That's marvelous! I'm really glad. Just be grateful you don't have to work with me every day, banging on about minimalism... :)

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.