The latest ASP.NET MVC version, hand in hand with WebPages
technology, brings us a new set of productivity helpers that are quite
interesting in the namespaces System.Web.Helpers. Among them we find
WebGrid, which finally offers a powerful and flexible default solution
to help us implement this useful feature in our applications.
Let’s see, step by step and in a completely practical manner, how to use WebGrid.
1. First: the Model

The
first thing we need before we begin to go in depth in the WebGrid
helper is a Model, the app’s data entities as well as the tools that
enables us to make persistant and recover the information from the
storage system we are using.
In this case, we are going to use as a repository a SQL Express
database with a single table, in which we have stored some people’s
data; this collection is the one we want to display in a datagrid.
Therefore, we have to fill it in with data to test it later.
In order to access the database we are going to use Entity Framework.
To do so we are going to need an Entity Data Model (a conceptual entity
model), which we can add to the project’s Models folder by
selection the ”Add new item” option from the context menu. In the wizard
that comes up, we only have to indicate it that we are going to
generate the model from an exisiting database, and finally we select the
table “People”. One we’ve finished this operation, we already have the
basic data infrastructure for our application.
The next step is to create a services class, which provides the
business logic and data access to our system. Obviously this does not
always have to be this way, since it depends on our needs and the
software’s architecture, and in our example both are going to be quite
simple.
The starting code for our services class is as follows:
01 | public class ModelServices: IDisposable { |
02 | private readonly Entities entities = new Entities(); |
03 | public IEnumerable GetPeople() |
05 | return entities.People.ToList(); |
As you can see in the previous code, we have a single method called
GetPeople(), which returns the complete set of people stored in the database.
And for now this is all the Model we need for the time being.
2. The controller
Our controller class, which we’ll call
PeopleController, in this first approach is going to be really simple. A single action,
Index(), which returns a view which we will supply the data collection obtained from the Model to:
01 | public class PeopleController : Controller |
03 | public ActionResult Index() |
05 | var data = new ModelServices().GetPeople(); |
An this is it: an action two lines. OK, it could have been performed
in a single line, but this way the code is more readible ;-)
3. The View, take one: WebGrid comes into scene
Now it’s when we really begin to notice the advantages of using
WebGrid versus other options available until MVC and that we have
mentioned at the top of this post.
Look at the following code, a Razor view that receives an number of
Person objects form the controller and generates a complete grid:
01 | @model IEnumerable<Person> |
03 | ViewBag.Title = "People"; |
04 | WebGrid grid = new WebGrid(Model); |
Impressing, isn’t it? Even though it seems incredible, the previous
code is all we need to build a completely functional grid, with paging
and column order: two lines! In the first line we instance the WebGrid
providing it the data collection on which it has to iterate. In the
second one we generate the HTML markup we’ll send to the client. The
result of executing this code is displayed below:

Although it’s far from being perfect, the result is spectacular. The
helper’s default behaviour displays a column for each property that it
finds in the class on which it iterates, putting them in alphabetical
order. In addition, it uses the name of the properties as column
headings, and displays them as links to force the sort order by each one
of them, and it even enters in the footer a complete data page
navigation system. And the best thing is that all thid works directly,
without having to add more code lines :-)
Nevertheless, as always, these automatisms have a cost. On one hand,
we don’t control the columns to be displayed. Neither do we control the
format in which its values are shown (see, for instance, the date of
birth) nor their headings…
Normally we have to put in an extra effort (not much though) in order
to leave everything perfectly. Moreover, there is a serious performance
problem when the number of grid elements is large: both the sort
order and the paging are performed on memory with the total number of
items. Exagerating a bit, let’s suppose we have one million rows in the
database, one million objects will materialize on memory, will be
ordered according to the current criteria and, finally, only the ten
objects that a data page contains are displayed to the client. Further
on, we’ll see that there are some formulas to manage efficiently
these scenarios.
[Learn
MVC 4 step by step with the post author: 'Expert Web Development with
ASP.NET MVC 4' created and tutored by Jose M. Aguilar]
4. The View, take two: the columns I want, please
There are different formulas to specify the columns to be displayed
in a WebGrid. The first of them is by exclusion on the total set of
properties. Among many other aspects, we can specify in the GetHtml()
method an array of name properties which mustn’t be shown as columns.
For instance, taking the previous example, if we are interested in
showing the PersonId property, we could have substituted the last line
of the view for:
01 | @grid.GetHtml(exclusions: new[] {"PersonId"}) |
However, the previous approach is not very useful, since want we
generally want is to indicate the order in which the columns are
displayed, specify their headers, determine whether or not the columns
can be used as order criteria, etc. All this information is defined
in WebGridColumn objects. Despite there are other ways of doing it, we
habitually find in the columns parameter of the GetHtml() call an array
with the detail of the grid columns, like in the following example:
01 | @grid.GetHtml(columns: new [] { |
03 | grid.Column("Surname"), |
05 | grid.Column("BirthDate"), |
06 | grid.Column("Children") |
As we can see, we are passing in the columns parameter an array in
which each element is being generated by a call to the WebGrid Column()
method, in which first parameter we indicate the name of the property
that the column corresponds to. The result of executing the code using
this last code would be:

Somethings have improved, but we still have to tweak the way it is displayed.
5. The View, take three: the columns how I want, please
We still have to shore up several details for the grid to reach, at
least visually, reasonable standards. To customize each column we can
use the parameters form the Column() column generator method which we
have seen above:
- header, which allows to indicate the text shown in the header,
- canSort, which indicates if the column can be used as sort order criteria,
- format, which enables us to indicate a custom format for column content,
- style, which indicates CSS class that will be applied to all the column cells.
Of all of the above, only the format property deserves a special
mention. In it we can indicate, either through a Razor markup block or
through the lambda function, how the content of the property vinculated
to the column has to be formated. In the first case, we should start the
markup block with the Razor escape character (@) and follow it with the
code we want to send to the client. From inside we can make reference
to the object which is being evaluated by using @item, like in the
following example, where how to format the EMail column so it is
displayed as a mailto hyperlink:
02 | format: @<a href="mailto:@item.Email">@item.Email</a> |
We can also use the lambda function, which receives as parameter the
current item and returns a string (or a IHtmlString if it doesn’t have
to be encoded). For instance, next we’ll see how to use this possibility
to give format to the BirthDate column:
01 | grid.Column("BirthDate", |
02 | format: p=>p.BirthDate.ToShortDateString() |
Therefore, bearing in mind all the above, we can tweak the grid a bit
by using the following code. As a reminder, I’ll show the again the
complete code of the view, so you can see how it results entirely:
01 | @model IEnumerable<Person> |
03 | ViewBag.Title = "People"; |
04 | WebGrid grid = new WebGrid(Model); |
07 | @grid.GetHtml(columns: new [] { |
08 | grid.Column("Name", canSort: false), |
09 | grid.Column("Surname"), |
11 | format: @<a href="mailto:@item.Email">@item.Email</a> |
13 | grid.Column("BirthDate", |
15 | format: p=>p.BirthDate.ToShortDateString() |
17 | grid.Column("Children", |
In runtime we can see now how it’s almost finished:
6. The View, take four: And can’t I add custom columns?
Of course you can! In fact, you can do it by just adding columns like
before, except that we don’t have to link them to any Model class
property. This, combined with the flexibility of the custom format
(format parameter), offers us everything we need to create columns the
way we want to. The code below shows how to add an additional column
with links to the actions that would enable it, for instance, to edit or
delete a Person:
01 | @grid.GetHtml(columns: new [] { |
07 | @Html.ActionLink("Edit", "Edit", new { id=item.PersonId} ) |
09 | @Html.ActionLink("Delete", "Delete", new { id=item.PersonId} ) |
Notice how, to increase the code’s legibility, we are using the
special Razor tag that allows us to create mark up blocks for several
lines. The result is as follows:
7. The View, take five: I’d rather have it all as I want to
The WebGrid helper offers a bunch of extra customizing options that
we can set when both calling it’s different methods or doing so
directly. For instance GetHtml() enables us to indicate the following
parameters, besides those that we have already studied:
- headerStyle, footerStyle, rowStyle, alternatingRowStyle, and
selectedRowStyle enable to indicate the CSS classes to apply to the
header, footer, alternative data rows and selected row, respectively.
- caption, to specify a title for a table, which will be included in a tag.
- fillEmptyRows, set to true it makes each page have always the same number of rows, creating blank rows if needed.
- emptyRowCellValue indicates the value to be shown in the empty row cells.
- mode, enables specifying the type of paginator to be created,
choosing it through a combination of elements of the WebGridPagerModes
numbering:
- WebGridPagerModes.Numeric: the pagainator shows all the direct links to pages near the current one.
- WebGridPagerModes.FirsLast: links to go to the first or last data page are displayed.
- WebGridPagerModes.NextPrevious: links to go to next or previous page are displayed.
- WebGridPagerModes.All: all of the above at the same time.
- numericLinksCount: indicates the number of pages that will appear
whenever the mode contains the WebGridPagerModes.Numeric value.
- firstText, previousText, nextText, lastText, enables replacing the
texts that appear by default in the go to first, previousm next and last
page links respectively. Initially “<”, and “>>” is common.
For example, take a look at the following code and its runtime result
once we have created a pair of rules in the web page style sheet:
04 | alternatingRowStyle: "alternative-row", |
05 | headerStyle: "grid-header", |
06 | footerStyle: "foot-grid", |
07 | mode: WebGridPagerModes.All, |
08 | firstText: "<< First", |
09 | previousText: "< Previous", nextText: "Next >", |
12 | ... // column definition seen previously |
Also, the WebGrid builder itself enables editing several functional aspects of the grid using the following parameters:
- defaultSort, it indicates the column that will act as default order while no other one is specified.
- rowsPerPage (by default, 10), defines the number of rows that appear on each page.
- canPage, canSort, indicate respectively if the grid allows paging and sort order. By default it is set to true in both cases.
- fieldNamePrefix, it enables indicating the prefix that is going to
be used in the query string parameters used by the grid. This, for
instance, will allow us to show several grids simultaneously on the same
page, without interfering.
- selectionFieldName, sortFieldName, sortDirectionFieldName enable
indicating the name of the parameters used to keep the state of the
selecetd row, the ordering field, and the direction of the ordering.
WebGrid even enables working in Ajax mode. In other words, it is able
to display the different pages without loading the entire page. In this
case, we can use the ajaxUpdateContainerId and ajaxUpdateCallback
parameters, that allow us to indicate the element of the page where the
data will be displayed and a callback function that will be called after
updating the element.
No comments:
Post a Comment