views:

330

answers:

2

I'm wondering how to best tackle this, since what I have now works great for a hard-coded column in my view -- I'm wondering how I can extend it to allow the column to be dynamic.

CONTROLLER:

var dc = new DataContextDC();
return View(dc.items.Where(i=>i.IsPublic == true));

VIEW:

<% foreach (var grp in Model.GroupBy(s => s.GroupColumn)) { %>
    <%= Html.Encode(grp.Key) %>
    <% foreach (var item in grp) { %>
        <%= Html.Encode(item.Title) %>
    <% } %>
<% } %>

As stated, the objective is to let the user choose which column replaces "GroupColumn" above. I'd like to avoid adding any external libraries, etc.

I see using reflection (slow, but fully dynamic) or since this is one View in my application, I just duplicate the above code for each column in the database and then put a switch statement on it (quick, and dirty, but effective)

+1  A: 

You can use Dynamic Linq:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

BFree
Is this library production ready? Is it free to use in closed source apps?
Nate Bross
IMHO libraries aren't production ready until YOU write tests to cover your usage scenarios.
jfar
@jfar Do you really write tests to verify that System.String works before you use String objects in production?
Nate Bross
@Nate Bross Ahh, a straw man. I love those.
jfar
+3  A: 

This is probably the kind of thing that you're going to want to use the Linq Dynamic Query library included with the C# Linq samples. That way, you can write the query like this:

var groups = Model.GroupBy("SomeColumn, SomeOtherColumn")

...which is a great deal easier to manage if you're accepting column names from the user - most likely all you have are the column names as strings, and this library will automatically parse those out into lambda expressions for you. (You need to catch ParseException if you expect the possibility of invalid input).

For formatting the key, you can probably just pass it in directly to the Html.Encode method, as its default string representation is something like { ID = 1, Name = Test }. If that's good enough then I would leave it alone, otherwise you'll have to use Reflection to parse out the individual key properties and property values.

Edit: You can use that library anywhere, if you download the samples you'll see that it is just a source code file.

Aaronaught
What would be the best practice? Should I compile the .CS file separatly? or should I just include it in my own project?
Nate Bross
@Nate Bross: There's no specific best practice; if you foresee the possibility that you might reuse the functionality in a different app, then compile it as a separate library (there's already a `.sln` for you to do that), otherwise either way works. It's MSPL so you can basically do anything you want with it; the only thing you can't do is redistribute the source file itself without the copyright line at the top.
Aaronaught
OK, call me stupid, but I cannot get this code to work in the View, it works in my Controller, but I can't figure out how to add the `using System.Linq.Dynamic` to the view and `<%@ Import ... %>` isn't working either is there something I'm missing?
Nate Bross
@Nate Bross: If you plan to use this on multiple pages, it's probably best to add the assembly and namespace to the web.config file. See here: http://www.west-wind.com/WebLog/posts/753705.aspx (the sections you care about are `system.web/pages/namespaces` and `system.web/compilation/assemblies`. If that's not working... post the code/config you used.
Aaronaught