Make the GridView control accessible

Apr 21, 2006

The GridView is a new web control in ASP.NET 2.0 and is an improvement of the old DataGrid. One of the biggest issues with the DataGrid was the lack of standard compliance and accessibility. This has been fixed in the new GridView along with a lot of other things as well.

When setting the property UseAccessibleHeader = true, it replaces the <td> elements of the header row with the correct <th> which means table header. It also adds the scope property of these header elements making them more accessible.

For some strange reason, there is no property for setting the <thead>, <tbody> and <tfoot> elements which are more important from an accessibility point of view. There is however an easy way of adding these elements in C# and VB.NET.

Let’s add a simple GridView to our page like this:

<asp:GridView runat="server" ID="gvFlowers" />

To add the extra elements, we need this simple method in the code-behind:

private void MakeAccessible(GridView grid)
{
 if (grid.Rows.Count > 0)
 {
  //This replaces <td> with <th> and adds the scope attribute
  grid.UseAccessibleHeader = true;

  //This will add the <thead> and <tbody> elements
  grid.HeaderRow.TableSection = TableRowSection.TableHeader;

  //This adds the <tfoot> element. Remove if you don't have a footer row
  grid.FooterRow.TableSection = TableRowSection.TableFooter;
 }
}

Then we just call the method from the Page_Load event like this:

protected void Page_Load(object sender, EventArgs e)
{
 //Add data to the GridView
 ...

 MakeAccessible(gvFlowers);
}

And this is the actual HTML that is generated:

<table cellspacing="0" rules="all" border="1" id="gvFlowers" style="border-collapse:collapse;">
        <thead>
            <tr>
                <th scope="col">Name</th><th scope="col">Height</th><th scope="col">Width</th>
            </tr>
        </thead><tbody>
            <tr>
                <td>tulip.jpg</td><td>30</td><td>420</td>
            </tr><tr>
                <td>daisy.jpg</td><td>32</td><td>481</td>
            </tr><tr>
                <td>rose.jpg</td><td>54</td><td>530</td>
            </tr>
        </tbody><tfoot>

        </tfoot>
</table>

It is not apparent that you have to dig into the header and footer rows and add a TableSection. This should be done automatically or at least be easy to set through a property at design time. I think it is an obvious mistake, but luckily for us, it is easy to fix if you know where to look.

* $4.95/month BlogEngine.net Hosting – Click Here!

Comments (11) -

 Will Nossiter
Will Nossiter
4/28/2006 12:26:49 PM #

I'm trying to use the grid.FooterRow.TableSection = TableRowSection.TableFooter; with AllowPaging="true". This throws an error "The table  must contain row sections in order of header, body, then footer." Also the GridView renders in the order thead, tbody, tfoot. We need valid XHTML 1.0 Strict which requires thead, tfoot, tbody. Any ideas ?

 Mads Kristensen
Mads Kristensen
5/1/2006 5:12:38 PM #

You have to add the TableHeader as well, in order to get both thead, tbody and tfoot. You probably need to do some manual overrides of the GridView in order to change the order of these tags.

 Tony Roberts
Tony Roberts
5/5/2006 6:37:23 PM #

I'm getting the same "The table  must contain row sections in order of header, body, then footer" error but only when paging is enabled. When paging is not enabled, the sections are in the order of thead, tbody and tfoot exactly like your example. This seems to match what the error message is asking for. Any ideas? Have you gotten your example to work with paging enabled?

 Tom Robinson
Tom Robinson
5/17/2006 10:21:18 AM #

I also got the same error initially. I'm using paging, but not using a footer so I was able to comment out the following line of code:

grid.FooterRow.TableSection = TableRowSection.TableFooter;

It seems to work.

 Abishek Bellamkonda
Abishek Bellamkonda
8/18/2006 5:59:33 AM #

Hmmm... i had the same issue. It turns out that if i have PagerSettings.Position="TopAndBottom", i am getting it, otherwise its fine.

 Legends
Legends
1/16/2007 3:20:50 PM #

Cool, didn't know that before !
Thank you.

Stringy
Stringy
2/7/2007 3:12:07 PM #

Fantastic, thanks

 Diana
Diana
3/7/2007 2:53:46 PM #

that's great, thanks

 Remy Blaettler
Remy Blaettler
3/26/2007 1:08:26 PM #

I have a grid with a header, a pager and sorting enabled. This looks good after the initial load, but if I wanna sort a colum the thead tag disappears after the post back.
The
grid.HeaderRow.TableSection = TableRowSection.TableHeader;
is still set. Even after the OnSorted event.
Anyone saw something similar?

Michael Sync
Michael Sync Singapore
8/18/2007 2:52:52 AM #

How to assign CSS class to tbody? If I use RowStyle property, it is going to add the CSS class to all rows within tbody.

Peter Bremer
Peter Bremer Norway
6/5/2008 9:41:53 AM #

My problem is, I have a table that is connected to the SelectedValue of a DropDownList, and the table itself has selectable rows, controlling yet another table by it's SelectedValue (3-level master-detail relation).

The situation now is, that after choosing an item from the DropDownList, the first table is NOT available yet on the resulting Page_Load! I can put the accessibility code in Table_DataBound, but then the problem is that the table is not again databound when selecting one of it's rows, meaning it looses it's header and footer again...

Is the only solution really to put the accessibility code in both Page_Load and Table_DataBound, and check if the table exists? Is there no better solution?

Pingbacks and trackbacks (1)+

Comments are closed

About the author

Mads Kristensen

Mads Kristensen
Program Manager at the Microsoft Web Platform team and founder of BlogEngine.NET.

More...

Month List

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.