Como faço para que o Gridview renderize THEAD?

112

Como obtenho o GridViewcontrole para renderizar as <thead> <tbody>tags? Eu sei que .UseAccessibleHeadersfaz com que seja colocado em <th>vez de <td>, mas não consigo fazer o <thead>aparecer.

Andrew Bullock
fonte
Para sua informação: UseAccessibleHeader é "true" por padrão, então você não precisa defini-lo. msdn.microsoft.com/en-us/library/…
MikeTeeVee

Respostas:

187

Isso deve servir:

gv.HeaderRow.TableSection = TableRowSection.TableHeader;
Phil Jenkins
fonte
69
A HeaderRowpropriedade será nullaté que GridViewtenha sido vinculado aos dados, portanto, certifique-se de esperar até que a vinculação de dados ocorra antes de executar a linha de código acima.
bdukes
6
Como comentário abaixo, com ASP.NET 4.5, pelo menos após a vinculação não é tarde o suficiente - ele funciona no OnPreRender.
philw
Eu tenho um gridview com subcabeçalhos personalizados adicionados. Cada um desses subcabeçalhos mostra dados da fonte de dados. O motivo pelo qual eu queria renderizar theadé usá-lo no jQuery. No entanto, após renderizar o cabeçalho, o tbodyparece não estar disponível. O que pode estar faltando no meu caso?
bonCodigo,
1
Descobri que ainda havia problemas durante o postback e coloquei o código no evento databound que abordou todos os cenários.
James Westgate
Trago meus dados de um banco de dados quando o usuário clica em um botão. Nesse caso, o gridview está sem a tag thead. Qualquer ajuda?
touinta
25

Eu uso isso no OnRowDataBoundevento:

protected void GridViewResults_OnRowDataBound(object sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.Header) {
        e.Row.TableSection = TableRowSection.TableHeader;
    }
}
Neto Kuhn
fonte
7
Esta é a única solução que funcionou para mim. Quem projetou esses controles terríveis?
EKW
2
Inseri seu código no evento OnRowCreated e fiz com que funcionasse corretamente.
yougotiger
Esta é a melhor solução porque remove o risco (e a verificação necessária) de TableSection ser nula se nenhuma linha estiver dentro da DataSource.
EvilDr
1
Fyi, se o GridViewestiver dentro de um UpdatePanele um postback assíncrono for causado por algum outro controle, o OnRowDataBoundevento não será gerado, portanto, o código nesta resposta não será executado, resultando na GridViewreversão para renderização sem <thead>tags ... suspiro . Para direcionar este caso, enfie o código da resposta aceita no PreRendermanipulador de eventos do gridView (bem como a resposta de ASalvo sugere).
Mr.Z
Esta é a resposta correta, já que usa corretamente o fluxo de trabalho WebForms.
Marcel
10

O código na resposta precisa continuar Page_Loadou GridView_PreRender. Coloquei em um método que foi chamado depois Page_Loade obtive um NullReferenceException.

ASalvo
fonte
4
Você também pode colocar no DataBoundevento. grid.DataBound += (s, e) => { grid.HeaderRow.TableSection = TableRowSection.TableHeader; };
BrunoLM
4
Não sei se isso é diferente no .NET 4.5 agora ... mas estou obtendo o HeaderRow sendo nulo nos manipuladores de eventos _DataBound e _PreRender. Isso pode estar relacionado ao fato de eu estar usando o novo recurso "Model Binding" do ASP.NET Web Forms no gridView.
ClearCloud8 de
7

Eu uso o seguinte código para fazer isso:

As ifdeclarações que adicionei são importantes.

Caso contrário (dependendo de como você renderiza sua grade), você lançará exceções como:

A tabela deve conter seções de linha em ordem de cabeçalho, corpo e rodapé.

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);
}

O thisobjeto é meu GridView.

Na verdade, eu substituí o Asp.net GridView para fazer meu próprio controle personalizado, mas você pode colar isso em sua página aspx.cs e fazer referência ao GridView pelo nome em vez de usar a abordagem custom-gridview.

FYI: Eu não testei a lógica do rodapé, mas sei que isso funciona para cabeçalhos.

MikeTeeVee
fonte
5

Isso funciona para mim:

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;
    }
}

Isso foi tentado no VS2010.

Felipe Delgado
fonte
2

Eu sei que isso é antigo, mas aqui está uma interpretação da resposta de MikeTeeVee, para um gridview padrão:

página aspx:

<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;
        }

    }
Jonathan Harris
fonte
2

Crie uma função e use-a em seu PageLoadevento como este:

A função é:

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

O PageLoadevento é:

protected void Page_Load(object sender, EventArgs e) {
        if (!IsPostBack)
        {
            MakeGridViewPrinterFriendly(grddata);
        }
}
Rajpurohit
fonte
0

Você também pode usar jQuery para adicioná-lo. Isso evita o problema com TableRowSection.TableHeader que é descartado no PostBack.

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

Michael
fonte