Looking At The WebMatrix WebGrid
The WebGrid helper is designed for rendering data taken from a database or provided via some other means. It has built-in support for paging and sorting (although a bug in the Beta 1 prevents you sorting on null DateTime values), and also offers access to a number of other formatting and design configurations. The main constructor (method called to create a WebGrid object) takes a number of arguments (mostly optional) as follows:
| IEnumerable<object> source | The data that the grid will display |
| [Optional, Default Value(null)] IEnumerable<string> columnNames | The values that you want to appear as column headers. |
| [Optional, Default Value(null)] string defaultSort | The column that you want to have the grid sorted on by default |
| [Optional, Default Value(10)] int rowsPerPage | The number of rows you want per page |
| [Optional, Default Value(true)] bool canPage | If this is true (it is by default) the grid can be paged |
| [Optional, Default Value(true)] bool canSort | If this is true (it is by default) the grid can be sorted |
| [Optional, Default Value(null)] string ajaxUpdateContainerId | The id of the containing element for Ajax paging and sorting support |
| [Optional, Default Value(null)] string fieldNamePrefix | A value which prefixes the default querystring fields such as "sort" and "sortdir" |
| [Optional, Default Value(null)] string pageFieldName | A custom value to replace the default querystring "page" field |
| [Optional, Default Value(null)] string selectionFieldName | A custom value to replace the default querystring "row" field |
| [Optional, Default Value(null)] string sortFieldName | A custom value to replace the default querystring "sort" field |
| [Optional, Default Value(null)] string sortDirectionFieldName | A custom value to replace the default querystring "sortdir" field |
The first argument, source is not optional. The grid must have some data to display. This can be any IEnumerable
I'm going to use the simple Books.sdf file I created for previous articles to show a basic implementation of the WebGrid using some of these arguments. To start with, this example shows a WebGrid being built using the minimum amount of code. Two things are required - the creation of a valid WebGrid object with a source of data, and a call to the WebGrid.GetHtml() method to write the resulting table to the browser:
@{ var db = Database.Open("Books"); var sql = "Select BookId, Title, ISBN, Description, FirstName, LastName, Category, DatePublished " + "From Books Inner Join Authors on Books.AuthorId = Authors.AuthorId " + "Inner Join Categories on Books.CategoryId = Categories.CategoryId"; var books = db.Query(sql); var grid = new WebGrid(books); } @grid.GetHtml()
When rendered, you can see that the default behaviour is for all columns of data to be included in the grid, and for paging and sorting to be enabled with 10 rows per page:

Limiting the columns can be done through the columnNames argument. This just needs to be included in the constructor with an IEnumerable of strings (an array will do):
@{ var db = Database.Open("Books"); var sql = "Select BookId, Title, ISBN, Description, FirstName, LastName, Category, DatePublished " + "From Books Inner Join Authors on Books.AuthorId = Authors.AuthorId " + "Inner Join Categories on Books.CategoryId = Categories.CategoryId"; var books = db.Query(sql); var grid = new WebGrid(books, columnNames : new []{"BookId", "Title", "ISBN", "Category"}); } @grid.GetHtml()

Now it's time to look at another argument - the ajaxUpdateContainerId. This points to the container element that will provide partial updates via jQuery AJAX. To start with, we'll amend the previous code to include two items - a paragraph showing the current time, and a div for the grid:
@{ Layout = "~/Shared/_Layout.cshtml"; var db = Database.Open("Books"); var sql = "Select BookId, Title, ISBN, Description, FirstName, LastName, Category, DatePublished " + "From Books Inner Join Authors on Books.AuthorId = Authors.AuthorId " + "Inner Join Categories on Books.CategoryId = Categories.CategoryId"; var books = db.Query(sql); var columns = new []{"BookId", "Title", "ISBN", "Category"}; var grid = new WebGrid(books, columnNames : columns); } <p>The time is @DateTime.Now </p> <div id="grid"> @grid.GetHtml() </div>
Now, if you run the page and click one of the pager links, or a sorting link, you will see that the time changes, indicating that the whole page refreshes to display the new page of data or the re-sorted grid. The div with the id of "grid" will be the ajaxUpdateContainer, so that needs to be passed into the constructor. But there is one other thing to do, and that is to obtain the jquery library and make it available to the page. You can download jQuery from here: http://jquery.com/. Choose the compressed and minified version as it's the smallest for downloading to the browser. My sample so far has used a Layout page, which contains the <head> element. This is where the reference to the jQuery library needs to be made. So I add the downloaded file to a new folder called Scripts, and add the following to the head element:
<head> <title></title> <link href="@Href("~/Styles/StyleSheet.css")" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="@Href("~/Scripts/jquery-1.4.4.min.js")"></script> </head>
The contructor for the grid needs to be changed. In the example below, I have moved the code that creates an array for the columns outside of the grid constructor to save having to wrap it for display on my web site but I have also passed the id of the div to the ajaxUpdateContainerId parameter:
@{ Layout = "~/Shared/_Layout.cshtml"; var db = Database.Open("Books"); var sql = "Select BookId, Title, ISBN, Description, FirstName, LastName, Category, DatePublished " + "From Books Inner Join Authors on Books.AuthorId = Authors.AuthorId " + "Inner Join Categories on Books.CategoryId = Categories.CategoryId"; var books = db.Query(sql); var columns = new []{"BookId", "Title", "ISBN", "Category"}; var grid = new WebGrid(books, columnNames : columns, ajaxUpdateContainerId: "grid"); } <p>The time is @DateTime.Now </p> <div id="grid"> @grid.GetHtml() </div>
Now if you run the page and click the sorting or paging links, you see that the time does not change. The only thing that changes is the contents of the div.
If you don't want to allow sorting or paging, you need to pass false for the canPage or the canSort arguments:
var grid = new WebGrid(books, canSort : false, columnNames : columns, ajaxUpdateContainerId: "grid");
This results in a plain table of data and no sorting links.
So far, we have only looked at passing configuration data into the WebGrid constructor. Now we'll have a look at the optional arguments that the WebGrid.GetHtml() method takes:
| [Optional, Default Value(null)] string tableStyle | CSS style for the table |
| [Optional, Default Value(null)] string headerStyle | CSS style for the header |
| [Optional, Default Value(null)] string footerStyle | CSS style for the footer |
| [Optional, Default Value(null)] string rowStyle | CSS style for rows |
| [Optional, Default Value(null)] string alternatingRowStyle | CSS style for alternating rows. |
| [Optional, Default Value(null)] string selectedRowStyle | CSS style for selected row |
| [Optional, Default Value(true)] bool displayHeader | Whether to display the table header or not |
| [Optional, Default Value(false)] bool fillEmptyRows | If the number of rows on the current page is less than the rowsPerPage, empty rows are created if this is true. |
| [Optional, Default Value(null)] string defaultCellValue | The value for empty cells. By default, it's " " |
| [Optional, Default Value(null)] IEnumerable<WebGridColumn> columns | Columns to be included |
| [Optional, Default Value(null)] IEnumerable<string> exclusions | Columns to be excluded |
| [Optional, Default Value(3)] WebGridPagerModes mode | Pager display options |
| [Optional, Default Value(null)] string firstText | Replace the default << link for the first page |
| [Optional, Default Value(null)] string previousText | Replace the default > link for the next page |
| [Optional, Default Value(null)] string nextText | Replace the default > link for the next page |
| [Optional, Default Value(null)] string lastText | Replace the default >> link for the last page |
| [Optional, Default Value(5)] int numericLinksCount | Set the number of numeric links in the pager |
The first options all cover styling the table and its contents. Here's some css styles that illustrate this:
.table{ border : 1px solid #809FFF; background-color: #E6FFFF; color: #6078BF; border-collapse: collapse; } .header{ background-color: #6078BF; color: white; } .alternate{ background-color: #EEE6FF; }
Now if we apply these to the GetHtml method:
@grid.GetHtml( tableStyle : "table", alternatingRowStyle : "alternate", headerStyle : "header" )
we can see the result like this:

Now it's time to look at columns. Ideally, you would have some control over which columns of data are returned by the SQL query, but this may not always be the case, so you need some way of switching columns off. Or you might want one query to run, but to be able to determine which columns can be seen based on the current roles of the user. If you haven't set the columns for display in the constructor, you can do so here, either by specifying columns to include through the columns parameter, or by specifying which ones not to display through exclusions. The optional arguments for the column constructor are as follows:
| [Optional, Default Value(null)] string columnName | The column name |
| [Optional, Default Value(null)] string header | Header text if you don't want database field names |
| [Optional, Default Value(null) Func<object, object> format | Formatting to be applied to values |
| [Optional, Default Value(null)] string style | CSS styles to be applied to the content |
| [Optional, Default Value(true)] bool canSort | Switches sorting off when set to false |
To illustrate these at work, here's some more code followed by an image showing the result:
@grid.GetHtml( columns: grid.Columns( grid.Column( columnName : "BookId", header : "Id", canSort : false, style : "disabled"), grid.Column( columnName : "Title"), grid.Column( columnName : "Category"), grid.Column( columnName : "DatePublished", format: @<text>@item.DatePublished.ToShortDateString()</text>) ) )

Looking at the rendered grid you can see that only the columns specified have been included in the grid. Further, the BookId column has a new name, Id, and cannot be sorted on. To help give users a visual clue that this is read-only, the column has a CSS class applied which displays the values as a light grey colour. In addition, the DatePublished column has been formatted so that the DateTimes do not include the hours, minutes and seconds.
If you would like to play with the sample code presented in this article, this download includes a number of pages showing the concepts presented here together with a copy of the simple database used.
Currently rated 4.77 by 22 people
Rate Now!
Date Posted:
08 August 2010 09:33
Last Updated:
13 November 2012 10:23
Posted by:
Mikesdotnetting
Total Views to date:
42544



Comments
08 August 2010 11:14 from reav
So nice to finally see webgrid helper explained. Thank you, Mike!
Can you now show how to use some AJAX-powered forms?
13 August 2010 08:28 from EinarT
This was most useful to read and try! Nice to see Ajax in action. The next I am thinking about, is:
a. How select a row id and open a child window to edit data or add a new row.
b. How to select and return a row id when the grid is in a child window.
c. How to refresh the grid with a filter using Ajax.
Perhaps your next article will give some answers.
13 August 2010 12:36 from Mikesdotnetting
@EinarT
The next article does indeed provide one or two answers: http://www.mikesdotnetting.com/Article/155/WebMatrix-And-jQuery-Forms
23 August 2010 04:36 from infocyde
Thanks for sharing this, info has come in handy.
19 September 2010 11:01 from reav
how to use "selectedRowStyle" param? is there possible to determine, what row user selected?
20 September 2010 21:09 from Mikesdotnetting
@reav,
I confess I couldn't work that out which is why I didn't mention it in the article. It would appear that it allows you to provide a css style to the selected row, but I couldn't quite establish how it knew which row that was. There is also another parameter in the WebGrid constructor that refers to selectedRows, but I couldn't get that to do anything either. It's something I intended to revisit at the time, but it completely slipped my mind. I'll see what I can find out.
02 October 2010 08:51 from Mikesdotnetting
@reav,
You can make a grid selectable by using the GetSelectLink() helper:
20 October 2010 11:27 from Esh
Hi! Great article & really useful.
a) From where do you figure out all these parameters? Webmatrix documentation is quite brief.
b) When I try pagermode parameter as per above, WM throws error. (i.e. Webgrid(datasource, mode: 3)
Thanks in advance.
Esh
13 December 2010 21:38 from Ryan
This grid, much like all of microsoft's helpers leaks dom elements badly when coupled with ajax in IE7. Do you know of any solutions to this? I've hunted endlessly for a way to fix it.
14 December 2010 07:04 from Mikesdotnetting
@Ryan,
I suspect the culprit is the default way in which the jQuery call uses the .load(element, segment) option. The whole of the page is brought back, but only the Grid portion is updated. It's a bit like the Update Panel in that respect. Not very precise... I would implement a more efficient paging model and my own custom AJAX on the thing.
12 January 2011 14:20 from Max
It is possible to add an "edit" and "delete" column to the grid?
12 January 2011 22:42 from Mikesdotnetting
@Max,
Yes - that's very doable. Come back tomorrow and you will find a new post which covers that scenario.
:o)
09 March 2011 22:22 from Tom
This is a great tutorial - thanks Mike. The pagination is a real timesaver with WebGrid - but is there way to display the data outside of a table?
I can think of instances where a table isn't the most semantic solution, but where it'd be really helpful to use WebGrid's pagination feature.
09 March 2011 23:07 from Mikesdotnetting
@Tom,
Have a look at this: http://www.mikesdotnetting.com/Article/150/Web-Pages-Efficient-Paging-Without-The-WebGrid
02 October 2012 13:15 from vineet
Hi Mikesdotnetting,
I want to apply a specific class on full row on the value of a column in that row. Is this possible webgrid.
Regards,
Vineet
04 October 2012 07:38 from Mikesdotnetting
@vineet
You need to use client-side Javascript to do that with the current WebGrid.
09 October 2012 13:35 from oleg_harp
Thank you Mike!
How to render row order number instead of ID? It is simply with ROW_NUMBER in SQL Server 2005, 2008, but what is about Compact Edition? Is there a way to do it with WebGrid?
11 October 2012 08:24 from Mikesdotnetting
@oleg_harp
You will have to project the data into a new form, for example an anonymous object that includes a property that represents the "row number". You can use LINQ to do that.
11 October 2012 10:24 from oleg_harp
Thank you Mike. For me the game is not worth the candle.
23 October 2012 00:16 from Eric Schrepel
Pretty new, so dumb question likely. Using WebGrid to display data, working fine. But I want the data source for webgrid to update when user picks an item from an <input type="select"> dropdown field above the webgrid.
How do I pass the value from the dropdown field into parameters for the webgrid datasource and re-display the webgrid?
24 October 2012 13:41 from Mikesdotnetting
@Eric,
I believe I cover that scenario in this article: Displaying Search Results In A WebGrid
03 March 2013 05:13 from Philip Hunt
Is there a way of suppressing the repeated display of the category. In your example the words ASP.NET Development and Javascript are repeated against each book to which they apply. Is there a way of telling the browser to only display the value of that field when it changes from the previous line?
06 March 2013 06:02 from Mikesdotnetting
@Philip
I think you want something like the approach featured in this article: http://www.mikesdotnetting.com/Article/189/Efficiently-Displaying-Hierarchical-Data-With-The-jQuery-Accordion-In-Razor-Web-Pages
20 March 2013 20:19 from Brenton White
Is there a way to put an id=myTable (e.g., <table id=myTable class="grid"> in the rendered HTML? I need to refer to the table by ID for HTML2CSV export. Or, better yet, is there a way to export and save the data from the grid to CSV or Excel format? THANKS.
20 March 2013 21:21 from Mikesdotnetting
@Brenton,
You can't apply an ID to the rendered source except through jQuery, but you can put the grid in a div and then reference it like that:
div#myTable table{ ... }
Or you can read this article: Exporting The Razor WebGrid To Excel
20 March 2013 23:09 from Brenton White
MANY thanks. You couldn't have given me a better answer! Very much appreciated.