How to Create a Customized GridView with Multi-Level Headers in ASP.NET C# WebForms

0

Creating advanced data presentation in web applications often demands customized table layouts. In this post, we’ll walk through how to build a fully customized GridView with multi-level headers in ASP.NET Web Forms using C#.

We’ll cover:

  • Displaying a complex data structure (like grouped columns per category)

  • Dynamically injecting header rows

  • Binding SQL Server data to the GridView

Let’s get started!


📌 Scenario

You want to render a GridView like this:

Hour Date 710 810 TOTAL
Total A B C Total A B C Total

This is common in reporting dashboards where you have grouped data under certain categories (e.g., machine numbers, regions, etc.).


✅ Step 1: Define the GridView in ASPX

Use AutoGenerateColumns="false" and add specific columns for each data field:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
HeaderStyle-BackColor="#9AD6ED" HeaderStyle-ForeColor="#000000"
OnRowCreated="GridView1_RowCreated" CssClass="table table-bordered">
<Columns>
<asp:BoundField DataField="xHour" HeaderText="Hour" />
<asp:BoundField DataField="xDate" HeaderText="Date" />
<!-- 710 Group -->
<asp:BoundField DataField="T710_Total" HeaderText="Total" />
<asp:BoundField DataField="T710_A_RG" HeaderText="A_RG" />
<asp:BoundField DataField="T710_B_RG" HeaderText="B_RG" />
<asp:BoundField DataField="T710_C_RG" HeaderText="C_RG" />
<!-- 810 Group -->
<asp:BoundField DataField="T810_Total" HeaderText="Total" />
<asp:BoundField DataField="T810_A_RG" HeaderText="A_RG" />
<asp:BoundField DataField="T810_B_RG" HeaderText="B_RG" />
<asp:BoundField DataField="T810_C_RG" HeaderText="C_RG" />
<!-- Total Column -->
<asp:BoundField DataField="Total" HeaderText="Total" />
</Columns>
</asp:GridView>

✅ Step 2: Add a Multi-Row Header in Code-Behind

Now add an extra header row dynamically with OnRowCreated.

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridViewRow headerRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
headerRow.Cells.Add(CreateHeaderCell("Hour", 1));
headerRow.Cells.Add(CreateHeaderCell("Date", 1));
headerRow.Cells.Add(CreateHeaderCell("710", 4));
headerRow.Cells.Add(CreateHeaderCell("810", 4));
headerRow.Cells.Add(CreateHeaderCell("TOTAL", 1));
GridView1.Controls[0].Controls.AddAt(0, headerRow);
}
}
private TableHeaderCell CreateHeaderCell(string text, int colspan)
{
TableHeaderCell cell = new TableHeaderCell();
cell.Text = text;
cell.ColumnSpan = colspan;
cell.HorizontalAlign = HorizontalAlign.Center;
cell.BackColor = System.Drawing.ColorTranslator.FromHtml("#3AC0F2");
cell.Font.Bold = true;
return cell;
}

This code inserts a custom header row above the default one, with merged cells grouped by category.


✅ Step 3: Retrieve and Bind SQL Server Data

Bind your stored procedure or SQL query results to the GridView:

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
private void BindGrid()
{
GridView1.DataSource = GetData();
GridView1.DataBind();
}
private DataTable GetData()
{
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnSqlServer"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("sp_C_CO", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
}
return dt;
}

Make sure your stored procedure returns column names like:

xHour, xDate, T710_Total, T710_A_RG, ..., T810_Total, ..., Total

🎨 Step 4: Optional Styling with CSS

You can add Bootstrap classes or your own CSS for better UI:

.table-bordered th, .table-bordered td {
border: 1px solid #ccc;
padding: 8px;
text-align: center;
}



Post a Comment

0Comments

Post a Comment (0)