MvcContrib Grid Part 6 – Sorting
March 14, 2010 – 13:48
This is part 6 of a series about the MvcContrib Grid.
- Part 1 – Introduction
- Part 2 – New Syntax
- Part 3 – GridModels and GridRenderes
- Part 4 – Limitations of the WebFormsViewEngine
- Part 5 – The Action Syntax
- Part 6 – Sorting
- Part 7 – Auto-generated columns
I recently added single-column sorting support to the MvcContrib grid. This can be turned on by calling the “Sort” method on a grid declaration and accepting a parameter of type GridSortOptions in your controller actions.
Controller:
public ActionResult Sorting(GridSortOptions sort) { ViewData["sort"] = sort; var people = _peopleFactory.CreatePeople(); if(!string.IsNullOrEmpty(sort.Column)) { people = people.OrderBy(sort.Column, sort.Direction); } return View(people); }
View:
<%= Html.Grid(Model) .Sort(ViewData["sort"] as GridSortOptions) .Columns(column => { column.For(x => x.Id).Named("Person ID"); column.For(x => x.Name); column.For(x => x.Gender); column.For(x => x.DateOfBirth).Format("{0:d}"); }) %>
By calling the “Sort” method, this tells the grid that sorting should be enabled. This will generate sorting links for each column heading (note that currently sorting is enabled for all columns – there is no way to enable it for individual columns only. I’ll change this in a future release)
These sorting links will add two additional parameters to the querystring: Column and Direction. These can be handled in your controller action by taking as a parameter an object of type GridSortOptions.
Using this object, you can then sort your data using whatever mechanism you choose. Out of the box, MvcContrib provides an overload for the “OrderBy” extension method that takes a property name and a direction and delegates the sorting to IQueryable. However, use of this extension method is entirely optional.
This also works with the grid’s paging support, so if you want your data to be both paged and sorted then you can make a call to AsPagination (or by using a custom IPagination provider) after the call to OrderBy:
public ActionResult SortingAndPaging(int? page, GridSortOptions sort) { ViewData["sort"] = sort; var people = _peopleFactory.CreatePeople(); if (!string.IsNullOrEmpty(sort.Column)) { people = people.OrderBy(sort.Column, sort.Direction); } people = people.AsPagination(page ?? 1, 10); return View(people); }
…and the results will be as expected.
When a column is sorted, the CSS classes of “sort_asc” or “sort_desc” will be applied to the relevant <th> element, so you can style the column headings (for example, by adding up/down arrows).
28 Responses
Has the GridSortOptions in this example been published as ColumnSortOptions? Or have I received the wrong version?
No, it is called GridSortOptions. The ColumnSortOptions was part of the old sorting implementation which has now been removed. You’ll need to grab the latest code from CodePlex in order to get these changes.
When specifying a column that contains an ActionLink, the element is missing “Column=” but it does have “Direction=” specified. Is the syntax shown below correct for specifying a sortable column containing an ActionLink?
column.For(c => Html.ActionLink(c.Id.ToString(), “Index”, “Home”, new { id = c.Id }, null)).Named(“Id”).DoNotEncode();
Martin,
Please add an issue for this on the codeplex issue tracker – at the moment the grid sorting only works with columns that are bound to a particular property and does not support more complex expressions.
Jeremy, Thanks, i’ve added an issue on codeplex. I’m using the following alternative sytax that works with sorting:
column.For(c => c.Id).Named(“Id”).Action(a =>
{%>
<%});
The Grid sorting functionality is excellent.
Is is possible to format the link to include additonal parameters in the same way the Pager allows using the .Link() method to format the link?
Currently the link redners as :
href=”/search?Column=Id&Direction=Descending”
I would like to do something like this:
href=”/search?Column=Id&Direction=Descending&q1=24&q2=ab”
@lmf232s,
Not currently. Feel free to create an issue for this on the MvcContrib issue tracker – http://mvccontrib.codeplex.com/workitem/list/basic
Ah, after looking over the code I see that you do append the existing querystring. I should be able to work with that but it would also be nice to format the link. I did create an issue.
Thanks!
I am having a very hard time to find where to specify the column for which to sort a column that has a “composite” content. For example the following column:
column.For(x => x.Name + x.Test).Named(“Name”);
If I want to order this for “x.Test” where can I specify this?? As a default it doesn’t add to the querystring the “Column” variable so it doesn’t order!
I have tried using the properties Header and HeaderAction to no avail.
Please help.
Marco,
This isn’t currently supported. There is an issue for this on the codeplex issue tracker, but I haven’t had time to look at it yet. I do accept patches though!
Jeremy,
Thanks for your quick reply. I sent you a very basic patch to add the “SortByColumn” function to the column object to specify the column name.
I hope it will be of some help.
Jeremy,
Would the SortByColumn patch help with a scenario where you are trying to render a sortable hyperlink column? I’m having trouble getting the Column querystring parameter to render when using the following.
column.For(merch => Html.ActionLink(merch.MerchantName, “Details”, new { id = merch.MerchantNumber })).Named(“Merchant Name”).DoNotEncode();
Thanks,
Brad
I’m interested to know what the recommended approach is to sorting when paging is involved. If the collection is coming from a repository which is only bringing back the required chunk (page) of objects from the datastore, then I guess it will also have to know the sort order before creating the correct ‘page’?
Brad,
Yes – the SortColumnName method which is in the latest commit will allow you to do this.
Sosh,
Correct – you should apply the sorting logic before the paging the data. If you’re using a composable query language (such as linq or NHibernate criteria) then this should be trivial to do.
The sample code from my c4mvc presentation has an example of this (see http://www.jeremyskinner.co.uk/2010/04/28/mvccontrib-grid-presentation/ )
Ok thanks Jeremy. One question regarding the .AsPagination() extension method then… Can I use this to convert a set of results that already contains only the correct records for the requested page? (e.g. from a repository that knows what page of results to get). Or, Does AsPagination expect the full set of results for it to pare down? (In this case I suppose I will have to create my own type which implements IPagination).
Sosh,
You can use the CustomPagination class for this.
Aha, works a treat – thanks.
http://mvcajax.codeplex.com/ does it with ajax, which is preferred. Can we get these merged?
Hi Jeremey,
Like Sme I also cannot find the GridSortOptions only GridSortOptions using the MVC 1 release. Has this been maintained with the MVC 2 or is the documentation now postdate this library?
Is there still the old documenation anywhere? As I cannot find it and am unfortunately not in a position to upgrade the project to MVC 2.
Thanks
Anthony
Anthony,
This is only in the MVC2 release – the MVC1 release is not being maintained and I have no plans to back-port it.
You could probably look through the MvcContrib wiki history to see the old grid documentation, but I would seriously recommend against using the old sorting functionality.
Thanks for letting me know but I tried that (the codeplex documentation anyway) and found nothing, as most of the documentation wasnt originally in there (afaik)
Scratch that I found it using the search feature, rather than trawling
No I was wrong I’d searched the wrong thing (having a bad afternoon), any links would be appreciated
The only docs are at http://mvccontrib.codeplex.com/wikipage?title=Grid&referringTitle=Documentation, but I’m afraid this is only for the MVC2 version.
The old sorting implementation (which I did not develop and actually never worked properly) was never documented as far as I know.
If you have any specific questions then feel free to ask on the mailing list and I’ll do my best to help, but development of an MVC1-compatible MvcContrib is essentially dead.
I’ve worked out how the old stuff works anyway thanks anyway
Just stick a .Sortable(true) on each column all done!
I can’t find GridSortOptions in MvcContrib 2.0.71.0 dll.
By any chance you reverted it to ColumnSortOptions. GridSortOptions is there in 2.0.36.0.
Any clue?
Morin,
It sounds like you’re using an old version. The class is called GridSortOptions (in MvcContrib.UI.Grid) – there is no ColumnSortOptions class.