example - gridview asp.net c# sql server
ASP.NET GridView segunda fila de encabezado para abarcar la fila del encabezado principal (9)
Agregar t.EnableViewState = false;
después de agregar la fila:
Dim t As Table = TryCast(grid.Controls(0), Table)
If t IsNot Nothing Then
t.Rows.AddAt(0, row)
End If
t.EnableViewState = false;
Tengo un GridView ASP.NET que tiene columnas que se ven así:
| Foo | Bar | Total1 | Total2 | Total3 |
¿Es posible crear un encabezado en dos filas que se vea así?
| | Totals |
| Foo | Bar | 1 | 2 | 3 |
Los datos en cada fila se mantendrán sin cambios, ya que esto es solo para mejorar el encabezado y disminuir el espacio horizontal que ocupa la cuadrícula.
El GridView completo se puede ordenar en caso de que importe. No pretendo que la columna de extensión "Totales" agregada tenga ninguna funcionalidad de ordenación.
Editar:
Basado en uno de los artículos que figuran a continuación, creé una clase que hereda de GridView y agrega la segunda fila de encabezado.
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);
}
}
}
En caso de que seas nuevo en ASP.NET como yo, también debo señalar que debes:
1) Registre su clase agregando una línea como esta a su formulario web:
<%@ Register TagPrefix="foo" NameSpace="CustomControls" Assembly="__code"%>
2) Cambie asp: GridView en su marcado anterior para foo: TwoHeadedGridView. No olvides la etiqueta de cierre.
Otra edición:
También puede hacer esto sin crear una clase personalizada.
Simplemente agregue un controlador de eventos para el evento DataBound de su cuadrícula de esta manera:
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);
}
}
}
La ventaja del control personalizado es que puede ver la fila de encabezado adicional en la vista de diseño de su formulario web. Sin embargo, el método del controlador de eventos es un poco más simple.
Deberá crear una clase que extienda gridview y anular el método CreateRow.
prueba this como punto de partida
Eche un vistazo a este artículo Encabezado de cuadrícula de columna de múltiples filas dinámicas
Pero cuando guardas datos, y si ocurre un error en el servidor, se producirán desalineamientos de filas
Por favor, consulte https://.com/a/9333714/1060656
Creé este ejemplo de solución
Para ejecutar en su sistema local necesitará crear 2 archivos (uno para el control y otro para aspx). Puede hacerlo en un proyecto o en 2 proyectos.
- GridViewPlus ==> Clase de control
- GridViewPlusCustomHeaderRows ==> una colección para mantener la clase de encabezado personalizado
- CustomHeaderEventArgs ==> Event Args cuando se crea una fila de encabezado personalizado
archivo aspx ==> Programa de prueba
public class GridViewPlus : GridView { public event EventHandler<CustomHeaderEventArgs> CustomHeaderTableCellCreated; private GridViewPlusCustomHeaderRows _rows; public GridViewPlus() : base () { _rows = new GridViewPlusCustomHeaderRows(); } /// <summary> /// Allow Custom Headers /// </summary> public bool ShowCustomHeader { get; set; } [PersistenceMode(PersistenceMode.InnerDefaultProperty)] [MergableProperty(false)] public GridViewPlusCustomHeaderRows CustomHeaderRows { get {return _rows; } } protected virtual void OnCustomHeaderTableCellCreated(CustomHeaderEventArgs e) { EventHandler<CustomHeaderEventArgs> 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<CustomHeaderEventArgs>(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(); } }
Quería hacer una tarea similar, pero se necesitaban botones en los que se pudiera hacer clic dentro del encabezado; ninguno de los anteriores funcionaba en ese caso, ya que los controladores de eventos no estaban conectados (debido a la secuencia de los eventos). Al final usé la etiqueta headertemplate en el campo de plantilla apropiado de la vista de cuadrícula. El html parece un poco más hinchado, pero los eventos permanecen intactos sin ningún código adicional detrás del esfuerzo. Por ejemplo
<asp:TemplateField >
<HeaderTemplate>
<div>
<div style="text-align: center;padding-bottom: 5px;">
text
</div>
<div>
<asp:Button ID="Button1" runat="server" Text="Apply to all" ToolTip="Apply to all - Special Bolt On" CssClass="sub_button input_btn_5" OnClick="ApplyButton1_Click" />
</div>
</div>
</HeaderTemplate>
<ItemTemplate>....
Tomé el enfoque de respuesta aceptada, pero agregué el encabezado al GridView existente en lugar de un GridView heredado personalizado.
Después de vincular mi GridView, hago lo siguiente:
/*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*/
Este artículo debe señalarte en la dirección correcta. Puede crear programáticamente la fila y agregarla a la colección en la posición 0.
Nota para aquellos que eligen usar RowDataBound Method en VB.NET
Si termina con demasiadas filas de encabezado adicionales apareciendo, agregue una instrucción If que solo continúe si la fila de encabezado de gridview no es nada (lo que significa que es la que se está enlazando actualmente)
If grid.HeaderRow Is Nothing Then