GridView do ASP.NET segunda linha de header para expandir a linha do header principal

Eu tenho um GridView do asp.net que tem colunas que se parecem com isso:

| Foo | Bar | Total1 | Total2 | Total3 | 

É possível criar um header em duas linhas que se parece com isso?

 | | Totals | | Foo | Bar | 1 | 2 | 3 | 

Os dados em cada linha permanecerão inalterados, pois isso é apenas para aumentar o header e diminuir o espaço horizontal ocupado pela grade.

O GridView inteiro é classificável caso isso seja importante. Não pretendo que a coluna de abrangência “Totais” adicionada tenha qualquer funcionalidade de sorting.

Editar:

Com base em um dos artigos abaixo, criei uma class que herda do GridView e adiciona a segunda linha de header em.

 namespace CustomControls { public class TwoHeadedGridView : GridView { protected Table InnerTable { get { if (this.HasControls()) { return (Table)this.Controls[0]; } return null; } } protected override void OnDataBound(EventArgs e) { base.OnDataBound(e); this.CreateSecondHeader(); } private void CreateSecondHeader() { GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal); TableCell left = new TableHeaderCell(); left.ColumnSpan = 3; row.Cells.Add(left); TableCell totals = new TableHeaderCell(); totals.ColumnSpan = this.Columns.Count - 3; totals.Text = "Totals"; row.Cells.Add(totals); this.InnerTable.Rows.AddAt(0, row); } } } 

Caso você seja novo no ASP.NET como eu, também devo salientar que você precisa:

1) Registre sua class adicionando uma linha como esta no seu formulário web:

  

2) Altere asp: GridView na sua marcação anterior para foo: TwoHeadedGridView. Não esqueça a tag de fechamento.

Outra edição:

Você também pode fazer isso sem criar uma class personalizada.

Basta adicionar um manipulador de events para o evento DataBound de sua grade da seguinte forma:

 protected void gvOrganisms_DataBound(object sender, EventArgs e) { GridView grid = sender as GridView; if (grid != null) { GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal); TableCell left = new TableHeaderCell(); left.ColumnSpan = 3; row.Cells.Add(left); TableCell totals = new TableHeaderCell(); totals.ColumnSpan = grid.Columns.Count - 3; totals.Text = "Totals"; row.Cells.Add(totals); Table t = grid.Controls[0] as Table; if (t != null) { t.Rows.AddAt(0, row); } } } 

A vantagem do controle personalizado é que você pode ver a linha de header extra na exibição de design do formulário da web. O método manipulador de events é um pouco mais simples, no entanto.

Este artigo deve apontar você na direção certa. Você pode criar a linha de forma programática e adicioná-la à coleção na posição 0.

Tomei a abordagem de resposta aceita, mas adicionei o header ao GridView existente em vez de um GridView herdado personalizado.

Depois de vincular meu GridView, faço o seguinte:

 /*Create header row above generated header row*/ //create row GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal); //spanned cell that will span the columns I don't want to give the additional header TableCell left = new TableHeaderCell(); left.ColumnSpan = 6; row.Cells.Add(left); //spanned cell that will span the columns i want to give the additional header TableCell totals = new TableHeaderCell(); totals.ColumnSpan = myGridView.Columns.Count - 3; totals.Text = "Additional Header"; row.Cells.Add(totals); //Add the new row to the gridview as the master header row //A table is the only Control (index[0]) in a GridView ((Table)myGridView.Controls[0]).Rows.AddAt(0, row); /*fin*/ 

texto alternativo

Nota para aqueles que optam por usar o método RowDataBound no VB.NET

Se você acabar com muitas linhas de header extras aparecendo, adicione uma instrução If que só prossiga se a linha de header da gridview não for nada (o que significa que ela está sendo ligada)

  If grid.HeaderRow Is Nothing Then 

Você terá que criar uma class que amplie o gridview e depois replace o método CreateRow.

tente isso como um ponto de partida

Mas quando você salva dados, e se ocorrer um erro no servidor, o desalinhamento de linhas ocorrerá

Adicione t.EnableViewState = false; depois de adicionar a linha:

 Dim t As Table = TryCast(grid.Controls(0), Table) If t IsNot Nothing Then t.Rows.AddAt(0, row) End If t.EnableViewState = false; 

Por favor, consulte https://stackoverflow.com/a/9333714/1060656

Eu criei este exemplo de solução

Para rodar em seu sistema local, será necessário criar dois arquivos (um para o controle e um aspx). Você pode fazer um projeto ou dois projetos.

  1. GridViewPlus ==> Classe de controle
  2. GridViewPlusCustomHeaderRows ==> uma coleção para manter a class de header personalizada
  3. CustomHeaderEventArgs ==> Argumentos de evento quando a linha de header personalizada é criada
  4. arquivo aspx ==> Programa de teste

     public class GridViewPlus : GridView { public event EventHandler CustomHeaderTableCellCreated; private GridViewPlusCustomHeaderRows _rows; public GridViewPlus() : base () { _rows = new GridViewPlusCustomHeaderRows(); } ///  /// Allow Custom Headers ///  public bool ShowCustomHeader { get; set; } [PersistenceMode(PersistenceMode.InnerDefaultProperty)] [MergableProperty(false)] public GridViewPlusCustomHeaderRows CustomHeaderRows { get {return _rows; } } protected virtual void OnCustomHeaderTableCellCreated(CustomHeaderEventArgs e) { EventHandler handler = CustomHeaderTableCellCreated; // Event will be null if there are no subscribers if (handler != null) { // Use the () operator to raise the event. handler(this, e); } } protected override void OnRowCreated(GridViewRowEventArgs e) { if (ShowCustomHeader && e.Row.RowType == DataControlRowType.Header) return; base.OnRowCreated(e); } protected override void PrepareControlHierarchy() { //Do not show the Gridview header if show custom header is ON if (ShowCustomHeader) this.ShowHeader = false; base.PrepareControlHierarchy(); //Safety Check if (this.Controls.Count == 0) return; bool controlStyleCreated = this.ControlStyleCreated; Table table = (Table)this.Controls[0]; int j = 0; if (CustomHeaderRows ==null )return ; foreach (TableRow tr in CustomHeaderRows) { OnCustomHeaderTableCellCreated(new CustomHeaderEventArgs(tr,j)); table.Rows.AddAt(j, tr); tr.ApplyStyle(this.HeaderStyle); j++; } } } public class GridViewPlusCustomHeaderRows : System.Collections.CollectionBase { public GridViewPlusCustomHeaderRows() { } public void Add(TableRow aGridViewCustomRow) { List.Add(aGridViewCustomRow); } public void Remove(int index) { // Check to see if there is a widget at the supplied index. if (index > Count - 1 || index < 0) // If no widget exists, a messagebox is shown and the operation // is cancelled. { throw (new Exception("Index not valid")); } else { List.RemoveAt(index); } } public TableRow Item(int Index) { // The appropriate item is retrieved from the List object and // explicitly cast to the Widget type, then returned to the // caller. return (TableRow)List[Index]; } } public class CustomHeaderEventArgs : EventArgs { public CustomHeaderEventArgs(TableRow tr ,int RowNumber ) { tRow = tr; _rownumber = RowNumber; } private TableRow tRow; private int _rownumber = 0; public int RowNumber { get { return _rownumber; } } public TableRow HeaderRow { get { return tRow; } set { tRow = value; } } } public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Example1(); GridViewExtension1.CustomHeaderTableCellCreated += new EventHandler(GridViewExtension1_CustomHeaderTableCellCreated); } void GridViewExtension1_CustomHeaderTableCellCreated(object sender, CustomHeaderEventArgs e) { TableRow tc = (TableRow)e.HeaderRow; tc.BackColor = System.Drawing.Color.AliceBlue; } private void Example1() { System.Data.DataTable dtSample = new DataTable(); DataColumn dc1 = new DataColumn("Column1",typeof(string)); DataColumn dc2 = new DataColumn("Column2",typeof(string)); DataColumn dc3 = new DataColumn("Column3",typeof(string)); DataColumn dc4 = new DataColumn("Column4",typeof(string)); // DataColumn dc5 = new DataColumn("Column5",typeof(string)); dtSample.Columns.Add(dc1); dtSample.Columns.Add(dc2); dtSample.Columns.Add(dc3); dtSample.Columns.Add(dc4); // dtSample.Columns.Add(dc5); dtSample.AcceptChanges(); for (int i = 0; i < 25; i++) { DataRow dr = dtSample.NewRow(); for (int j = 0; j < dtSample.Columns.Count; j++) { dr[j] = j; } dtSample.Rows.Add(dr); } dtSample.AcceptChanges(); //GridViewExtension1.ShowHeader = false; GridViewExtension1.ShowCustomHeader = true; /* *======================================================================= * |Row 1 Cell 1 | Row 1 Col 2 (Span=2) | Row 1 Col 3 | * | | | | *======================================================================= * |Row 2 Cell 1 | | | | * | | Row 2 Col 2 | Row 2 Col 3 |Row 2 Col 4 | *======================================================================= * * * * * */ // SO we have to make 2 header row as shown above TableRow TR1 = new TableRow(); TableCell tcR1C1 = new TableCell(); tcR1C1.Text = "Row 1 Cell 1"; tcR1C1.ColumnSpan = 1; TR1.Cells.Add(tcR1C1); TableCell tcR1C2 = new TableCell(); tcR1C2.Text = "Row 1 Cell 2"; tcR1C2.ColumnSpan = 2; TR1.Cells.Add(tcR1C2); TableCell tcR1C3 = new TableCell(); tcR1C3.Text = "Row 1 Cell 3"; tcR1C3.ColumnSpan = 1; TR1.Cells.Add(tcR1C3); GridViewExtension1.CustomHeaderRows.Add(TR1); TableRow TR2 = new TableRow(); TableCell tcR2C1 = new TableCell(); tcR2C1.Text = "Row 2 Cell 1"; tcR2C1.ColumnSpan = 1; TR2.Cells.Add(tcR2C1); TableCell tcR2C2 = new TableCell(); tcR2C2.Text = "Row 2 Cell 2"; tcR2C2.ColumnSpan = 1; TR2.Cells.Add(tcR2C2); TableCell tcR2C3 = new TableCell(); tcR2C3.Text = "Row 2 Cell 3"; tcR2C3.ColumnSpan = 1; TR2.Cells.Add(tcR2C3); TableCell tcR2C4 = new TableCell(); tcR2C4.Text = "Row 2 Cell 4"; tcR2C4.ColumnSpan = 1; TR2.Cells.Add(tcR2C4); GridViewExtension1.CustomHeaderRows.Add(TR2); GridViewExtension1.DataSource = dtSample; GridViewExtension1.DataBind(); } } 

Dê uma olhada neste artigo Cabeçalho de Grade de Coluna de Linha Múltipla Dinâmico

Eu queria fazer uma tarefa semelhante, mas precisava de botões clicáveis ​​dentro do header – nenhum dos itens acima funcionava nesse caso, pois os manipuladores de events não estavam conectados (devido ao sequenciamento dos events). No final, usei a tag headeremplate no campo de modelo apropriado da visualização de grade. O html parece um pouco mais inchado, mas os events permanecem intactos, sem nenhum código adicional por trás do esforço. Por exemplo

   
text
....