How do I get Gridview to render THEAD?
Asked Answered
O

8

121

How do I get the GridView control to render the <thead> <tbody> tags? I know .UseAccessibleHeaders makes it put <th> instead of <td>, but I cant get the <thead> to appear.

Orlan answered 21/11, 2008 at 15:27 Comment(1)
FYI: UseAccessibleHeader is "true" by default, so you don't need to set it. msdn.microsoft.com/en-us/library/…Paleoecology
L
199

This should do it:

gv.HeaderRow.TableSection = TableRowSection.TableHeader;
Lance answered 21/11, 2008 at 15:34 Comment(7)
The HeaderRow property will be null until the GridView has been data bound, so make sure to wait until databinding has occurred before running the above line of code.Openandshut
As comment below, with ASP.NET 4.5 at least after binding isn't late enough - it works in OnPreRender however.Pulsifer
I have a gridview with custom sub headers added. Each of these sub headers do show data from the data source. The reason I wanted to render thead is to use it in jQuery. However after rendering header, the tbody doesn't seem to be available. What may be missing in my case?Afterdinner
I found there was still problems during postback and placed the code in the databound event which addressed all scenarios.Erenow
I bring my data from a database when user clicks on a button. In that case the gridview is missing the thead tag. Any help?Powerdive
Must add gv.DataBind(); before.Vidicon
Add the ShowHeaderWhenEmpty="True" attribute to the GridView control if you want to render a grid with no rows.Niccolo
K
35

I use this in OnRowDataBound event:

protected void GridViewResults_OnRowDataBound(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.Header) {
        e.Row.TableSection = TableRowSection.TableHeader;
    }
}
Kwangtung answered 8/1, 2015 at 18:45 Comment(5)
This is the only solution that worked for me. Who designed these terrible controls?Nightspot
I inserted your code into the OnRowCreated event and got it to work correctly.Bullring
This is the best solution because it removes the risk (and required check) of the TableSection being null if no rows are within the DataSource.Inarticulate
Fyi, if the GridView is within an UpdatePanel and an async-postback is caused by some other control then the OnRowDataBound event won't be raised thus the code in this answer won't be executed, resulting in the GridView reverting to rendering without <thead> tags... sigh. To target this case, shove the code from the accepted answer into the gridView's PreRender event handler (much like ASalvo's answer suggests).Sterigma
This is the correct answer, as it properly uses the WebForms workflow.Culverin
D
10

The code in the answer needs to go on Page_Load or GridView_PreRender. I put it in a method that was called after Page_Load and got a NullReferenceException.

Deliquescence answered 30/4, 2009 at 20:16 Comment(2)
You can also put in DataBound event. grid.DataBound += (s, e) => { grid.HeaderRow.TableSection = TableRowSection.TableHeader; };Locular
Don't know if this is different in .NET 4.5 now... but I am getting the HeaderRow being null in both _DataBound and _PreRender event handlers. This might be related to the fact I am using ASP.NET Web Forms new "Model Binding" feature in the gridView.Illiterate
P
7

I use the following code to do this:

The if statements I added are important.

Otherwise (depending on how you render your grid) you'll throw exceptions like:

The table must contain row sections in order of header, body and then footer.

protected override void OnPreRender(EventArgs e)
{
    if ( (this.ShowHeader == true && this.Rows.Count > 0)
      || (this.ShowHeaderWhenEmpty == true))
    {
        //Force GridView to use <thead> instead of <tbody> - 11/03/2013 - MCR.
        this.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
    if (this.ShowFooter == true && this.Rows.Count > 0)
    {
        //Force GridView to use <tfoot> instead of <tbody> - 11/03/2013 - MCR.
        this.FooterRow.TableSection = TableRowSection.TableFooter;
    }
    base.OnPreRender(e);
}

The this object is my GridView.

I actually overrode the Asp.net GridView to make my own custom control, but you could paste this into your aspx.cs page and reference the GridView by name instead of using the custom-gridview approach.

FYI: I haven't tested the footer logic, but I do know this works for Headers.

Paleoecology answered 7/11, 2013 at 20:30 Comment(0)
O
5

This works for me:

protected void GrdPagosRowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.TableSection = TableRowSection.TableBody;
    }
    else if (e.Row.RowType == DataControlRowType.Header)
    {
        e.Row.TableSection = TableRowSection.TableHeader;
    }
    else if (e.Row.RowType == DataControlRowType.Footer)
    {
        e.Row.TableSection = TableRowSection.TableFooter;
    }
}

This was tried in VS2010.

Orthocephalic answered 23/6, 2014 at 19:1 Comment(0)
P
3

I know this is old, but, here's an interpretation of MikeTeeVee's answer, for a standard gridview:

aspx page:

<asp:GridView ID="GridView1" runat="server" 
    OnPreRender="GridView_PreRender">

aspx.cs:

    protected void GridView_PreRender(object sender, EventArgs e)
    {
        GridView gv = (GridView)sender;

        if ((gv.ShowHeader == true && gv.Rows.Count > 0)
            || (gv.ShowHeaderWhenEmpty == true))
        {
            //Force GridView to use <thead> instead of <tbody> - 11/03/2013 - MCR.
            gv.HeaderRow.TableSection = TableRowSection.TableHeader;
        }
        if (gv.ShowFooter == true && gv.Rows.Count > 0)
        {
            //Force GridView to use <tfoot> instead of <tbody> - 11/03/2013 - MCR.
            gv.FooterRow.TableSection = TableRowSection.TableFooter;
        }

    }
Ptolemy answered 22/11, 2016 at 17:13 Comment(0)
A
2

Create a function and use that function in your PageLoad event like this:

The function is:

private void MakeGridViewPrinterFriendly(GridView gridView) {  
    if (gridView.Rows.Count > 0) {          
        gridView.UseAccessibleHeader = true;  
        gridView.HeaderRow.TableSection = TableRowSection.TableHeader;  
    }  
} 

The PageLoad event is:

protected void Page_Load(object sender, EventArgs e) {
        if (!IsPostBack)
        {
            MakeGridViewPrinterFriendly(grddata);
        }
}
Aesthesia answered 5/4, 2013 at 9:26 Comment(0)
P
0

You can also use jQuery to add it. This avoids the problem with TableRowSection.TableHeader where gets dropped on PostBack.

$('#myTableId').prepend($("<thead></thead>").append($(this).find("#myTableId tr:first")));

Proglottis answered 26/7, 2019 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.