This project is read-only.

EnableSortingFor Helper for DataGrid sorting and in general for sorting any enumerable or queryable 

This control needs reference to MVCControlToolkit.Controls.Core-x.x.x.js

To enable sorting on some columns of the a DataGrid one can use the EnableSortingFor Helper together with a Sort DataButton.

As first step we put the data buttons in the columns header:

<table>
<tr>
<td colspan="4"> TO DO LIST</td>
</tr>
<tr>
<td class="HeaderContainer"><strong>@Html.SortButtonFor(m => m.Name, sortButtonStyle: SortButtonStyle.Button) </strong></td>
<td class="HeaderContainer"><strong>@Html.SortButtonFor(m => m.Description, sortButtonStyle: SortButtonStyle.Button)%></strong></td>
<td >Edit</td>
<td >Delete</td>
</tr>
@(ViewData["Content"] as MvcHtmlString)
</table>

The header name is taken from the ShortName or Name(if no ShortName is provided) properties of the DisplayAttribute of the column. However, we can also override this value through the use of the parameter Text.

As you can see the whole template of the DataGrid is defined in View that is strongly typed with the DataType of the items of the DataGrid. In general. the SortButtonFor  works only if it is created with the an HtmlHelper that is istantiated with the same DataType of the Grid Item.  If you  don't want use a DataGrid template but you would like to define the DataGrid in-line, you can use the SortButtonForTrackedCollection helper, instead, as shown below:

                <table>
                    <tr>
                    <td colspan="4"> TO DO LIST</td>
                    </tr>
                    <tr>
                    <td class="HeaderContainer"><strong>@Html.SortButtonForTrackedCollection(m => m.ToDoList, m => m.Name, sortButtonStyle: SortButtonStyle.Button)</strong></td>
                    <td class="HeaderContainer"><strong>@Html.SortButtonForTrackedCollection(m => m.ToDoList, m => m.Description, sortButtonStyle: SortButtonStyle.Button)</strong></td>
                    <td >Edit</td>
                    <td >Delete</td>
                    </tr>
                    @Html.DataGridFor(m => m.ToDoList, ItemContainerType.tr, 
                     "ToDoEditItem", "ToDoDisplayItem", null, "ToDoInsertItem", "ToDoUndeleteItem",
                     itemCss: "normalRow", altItemCss: "alternateRow"
                    )
                </table>

The SortButtonForTrackedCollection  helper is not specific for the use with a DataGrid but it can be used to sort any collection that uses the Tracker<T> object to perform Changes Tracking. If one wishes to sort a normal collection, one can use the SortButtonForCollection helper instead. In particular the SortButtonForCollection  can be used to sort grids built "manually" or with the SortableListFor helper, DropDowns, etc.

Together with the Sort buttons we have to insert the EnableSortingFor  helper itself in the same View as the DataGrid helper:

 @Html.EnableSortingFor(m => m.ToDoList, m => m.ToDoOrder, "NormalHeaderToDo", "AscendingHeaderToDo", "DescendingHeaderToDo", page: m => m.CurrPage)

 

 

The EnableSortingFor helper needs the collection the grid operates on, if there is paging it needs the variable the pager acts on and finally a property of  the type:

 

List<KeyValuePair<LambdaExpression, OrderType>>

That is used to exchange sorting information with the View Model. The OrderType enumeration specifies the kind of orderning (ascending or descending) while each LambdaExpression can be used directly into a Linq instruction.

"NormalHeaderToDo", "AscendingHeaderToDo", "DescendingHeaderToDo" are three css classes that are applied to the Sort Buttons depending of their sorting states. They might be used for instance to display the up/down arrows that represents the order selected.

In the MvcControlsToolkit.Linq namespace we have defined the ApplyOrder Linq extension that applies the whole lexicographic order defined by the list above to any IQueryable or IEnumerable. If X is the IEnumerable or IQueryable we need just to type X.ApplyOrder(order) where order is the Lexycographic order returned by the EnableSortingFor helper.

As a default clicking a Sort button doesn't cause an immediate post, abd we need to click a submit button (or something else) to see the effect of a new ordering. However, the EnableSortingFor helper has the causePostback parameter, that if set tto true causes an immediate post after a sort button is clicked.

The EnableSortingFor helper triggers a javscript event each time the sorting is changed by the user:

 

trigger("queryChanged", data)

 

Where the data object contains the fields:

  • type, specifies the kind of query information that changed. For the EnableSortingFor its value is the string: 'sort'.
  • submit, by setting this value to true within our event handler we can cause a form submit. By setting it to false we prevent a form submit.  The value passed initially in this field is the causePostback  of the EnableSortingFor helper.
  • page, the current page. After a change in the sorting its value is always 1 because the pager, if provided, is reset to the first page.
  • sortString: a string encoding actual sorting. It can be passed to other objects that can hndle it, such as any implementation of the mvcct.Queryable.

This event bubbles through the ancestors chain, so we can specify an event handler in any DOM ancestor of the pager. 

As a default selecting an ascending or descending sorting on a column just add this sorting to the already existing sorting. This means the items are sorted lexicographically  considering firts the previous columns, and then the newly added sorting. Thus, if we want the new sorting to substitute the previous one, we have, first to de-select the old sorting and then to add the new sorting. However, we can force also one column sorting mode, by setting the oneColumnSorting parameter of the helper to true. In such a case selecting a new sorting automatically remove the previous sorting.

is used just fordoesn't cause an immediate post, abd we need to click a submit button (or something else) to see the effect of a new ordering. However, the EnableSortingFor helper has the causePostback parameter, that if set tto true causes an immediate post after a sort button is clicked.

Finally, columns enabled for user sorting needs to be decorated with the CanSort attribute defined in the MvcControlsToolkit.DataAnnotations namespace. if a column without the CanSort attribute is returned in the lexicographic order it is automatically cancelled to avoid Denial of Service Attacks (a column might be difficult to sort, for instance, because there is no index defined on the database for that field).

Download  here a complete application example that shows the pratical use of sorting and see the its tutorial here.

Last edited Jun 22, 2014 at 11:52 AM by frankabbruzzese, version 26

Comments

No comments yet.