views:

351

answers:

1

In reporting tools like Crystal Reports, there are ways to take denormalized data and group it by a particular column in the data, creating row headings for each unique item in the specified column.

If I have this:

Category1    Data1
Category1    Data2
Category1    Data3
Category2    Data4
Category2    Data5
Category2    Data6

The reporting software will group it like this:

Category1
      Data1
      Data2
      Date3
Category2
      Data4
      Data5
      Data6

Is there a way to do this in an ASP.NET MVC view, perhaps using a simple linq phrase or linq extension method with a foreach or a nested foreach?

+6  A: 

If your view is strongly typed, you can use the LINQ GroupBy extension method with nested foreach:

<ul>
<% foreach (var group in Model.GroupBy(item => item.Category)) { %>

   <li><%= Html.Encode(group.Key) %>
     <ul>

     <% foreach (var item in group) { %>
       <li><%= Html.Encode(item.Data) %></li>  
     <% } %>

     </ul>
   </li>

<% } %>
</ul>

This will provide output much like your formatted lists in the original question. It assumes your model looks something like:

public class ViewModel
{
    public string Category { get; set; }
    public string Data { get; set; }
}
Jason
Shouldn't the data be grouped in the controller?
Bruno Lopes
@Bruno, I could do that, but then I would have to send two sets of data to the view...One for the categories, and one for the items. I'd rather not do that. Report generators have done this sort of thing for years. It makes sense to put it in the view.
Robert Harvey
Jason, thanks for this. I'm still learning linq. The weird thing is that I seem to understand it better when I use the extension method syntax (which works in all cases) instead of the (prettier but more opaque) language sugar they added to c#.
Robert Harvey
@Robert, re: grouping in the controller (via @Bruno), I'm confused why you would have to send the two sets of data to the view. Wouldn't you simply have a collection in your viewmodel of type IEnumerable<IGrouping<YourCategory, YourDataItem>>? I've done that a number of times and then just looped through the collection similar to Jason's example. Doesn't really have an effect on your app either way, just curious why you would have to send in the categories and items separately with that method?
mannish
That's pretty cool, Mannish. But to my eye it's also more complex. I'm used to dealing with flat datasets in reports, so I guess I just see this grouping as a View function. I also sense a bit of "political correctness" in putting it in the controller, but I don't find that point of view compelling.
Robert Harvey
Thank you for this! Exactly what I needed to see how to do
optician