How do I get Gridview to render THEAD?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
ASP.NET Web Forms GridView does not always emit a semantic table header section by default, which is why developers often end up with header rows rendered only as ordinary tr elements. If you want the control to output a real thead, the usual fix is to mark the header as accessible and assign the header row to TableHeader after data binding.
Why GridView Does Not Always Render thead
GridView is a server control, so the HTML it emits depends on its internal rendering rules. Even if the control visually shows a header row, that does not guarantee it will produce a thead section in the final markup.
That matters for a few reasons:
- screen readers understand table structure better
- CSS targeting of headers is cleaner
- client-side table plugins often expect semantic sections
- the markup is more correct and maintainable
So the problem is not "how do I style the header." The problem is "how do I make GridView render semantic header markup."
The Standard Fix in Code-Behind
The most common solution is:
- make sure the control has a header
- enable accessible header rendering
- set the header row section to
TableHeader
This is often done after the grid has been bound:
Code-behind:
The PreRender event is a good place for this because the rows already exist by then.
Why UseAccessibleHeader Matters
Setting HeaderRow.TableSection = TableRowSection.TableHeader is the key step, but UseAccessibleHeader = true is also important because it instructs the control to render header cells with th semantics instead of ordinary data cells.
Together, these settings produce the kind of output most developers expect:
- the header row is placed inside
thead - header cells render as
th - body rows stay inside
tbody
If you only set one of these properties, the output may still not be as semantic or predictable as you want.
Handle Empty Data Carefully
One reason the fix sometimes appears not to work is that the grid has no header row at all when there is no data. If HeaderRow is null, there is nothing to assign to TableHeader.
For grids that must show headers even when empty, configure the control accordingly and verify the final rendered HTML in the browser. The presence or absence of a data source affects whether HeaderRow exists during PreRender.
Another practical tip is to inspect the actual page source rather than relying on what the server control "should" be doing. Web Forms can be surprising if you only reason from markup and do not check the emitted HTML.
Common Pitfalls
The biggest mistake is setting TableSection too early, such as before the grid is bound. At that point the header row may not exist yet.
Another issue is forgetting UseAccessibleHeader = true. Without it, the control may still render a row, but not with the semantic header cell behavior you expect.
Developers also sometimes confuse design-time markup with runtime output. The important thing is what the browser receives, not what the .aspx file suggests.
Finally, when the grid is empty, HeaderRow can be null. If your logic does not guard against that case, the code either fails or silently does nothing.
Summary
- To get
GridViewto render a realthead, setUseAccessibleHeader = trueand assignHeaderRow.TableSection = TableRowSection.TableHeader. - Do this after data binding, commonly in the
PreRenderevent. - Check that
HeaderRowis notnullbefore modifying it. - Inspect the final HTML output to confirm the browser receives semantic table markup.
- If the grid is empty, you may need additional configuration to keep a header row available.

