GridView使用HeaderTemplate时首列(idemp)空白问题排查
解决GridView首列空白(使用HeaderTemplate后员工ID列不显示)的问题
问题描述
我尝试从MySQL数据库获取员工数据并在GridView中展示,使用HeaderTemplate自定义表头,但发现员工ID对应的第一列始终空白。以下是我的代码:
ASPX页面代码
<head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:GridView ID="GridView1" runat="server" Width="99%" GridLines="Both" OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="false"> <Columns> <asp:TemplateField> <HeaderTemplate> <tr> <th style="padding: 2.5px; width: 10%;" >eid</th> <th style="padding: 2.5px; width: 55%;" >First Name</th> <th style="padding: 2.5px;" >Last Name</th> </HeaderTemplate> </asp:TemplateField> <asp:BoundField DataField="idemp" /> <asp:BoundField DataField="fname" /> <asp:BoundField DataField="lname" /> <asp:TemplateField> <ItemTemplate> <asp:GridView ID="GridView2" runat="server" Width="99%" GridLines="Both" AutoGenerateColumns="false" CssClass="ChildGrid"> </asp:GridView> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </div> </form>
后台C#代码
namespace WebApplication2 { public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Populate the GridView. bindGridview(); } } public void bindGridview() { DataTable dt = new DataTable(); string constr = @"server=127.0.0.1;user id=root;pwd=n0711p2010p;database=emp"; using (MySqlConnection con = new MySqlConnection(constr)) { MySqlCommand cmd = new MySqlCommand("select idemp,fname,lname from emp", con); con.Open(); MySqlDataReader dtreader = cmd.ExecuteReader(); dt.Load(dtreader); if (dt.Rows.Count >0) { GridView1.DataSource = dt; GridView1.DataBind(); con.Close(); } } } //RowDataBound Event protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { //Checking the RowType of the Row if (e.Row.RowType == DataControlRowType.DataRow) { DataTable dt = new DataTable(); string constr = @"server=127.0.0.1;user id=root;pwd=n0711p2010p;database=emp"; using (MySqlConnection con = new MySqlConnection(constr)) { con.Open(); GridView child_gridview = (GridView)e.Row.FindControl("GridView2"); String CountryId = (e.Row.RowIndex+1).ToString(); MySqlCommand cmd = new MySqlCommand("select salary,post from emp where idemp="+CountryId, con); MySqlDataReader dtreader = cmd.ExecuteReader(); dt.Load(dtreader); if (dt.Rows.Count > 0) { child_gridview.DataSource = dt; child_gridview.DataBind(); } } } } } }
当前输出中GridView首列空白,希望解决该问题并实现预期展示效果。
问题原因分析
- 表头与数据列结构错位:你把整个表头行(
<tr>+三个<th>)放在了一个单独的TemplateField中,这个字段没有对应的ItemTemplate,导致数据行的第一列无内容显示,呈现空白。后续的BoundField数据列会排在这个空白列之后,造成表头和数据的错位。 - 子GridView未定义列:子
GridView2设置了AutoGenerateColumns="false"但未配置任何列,即使绑定数据也无法渲染内容。 - 子表数据查询逻辑错误:用
e.Row.RowIndex+1作为idemp的值查询子表数据不可靠——行索引不一定等于数据库中idemp的实际值,应该从当前数据行的绑定数据中直接获取。
解决方案
1. 修正ASPX页面的GridView结构
删除单独包裹表头的TemplateField,改为给每个BoundField设置自定义表头样式,同时为子GridView2添加列定义:
<head runat="server"> <title>Employee Details</title> <style> .ChildGrid { margin: 10px 0; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:GridView ID="GridView1" runat="server" Width="99%" GridLines="Both" OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="false"> <Columns> <!-- 员工ID列:绑定数据并设置表头样式 --> <asp:BoundField DataField="idemp" HeaderText="eid" ItemStyle-Width="10%" ItemStyle-Padding="2.5px" HeaderStyle-Padding="2.5px" HeaderStyle-Width="10%" /> <!-- 名字列 --> <asp:BoundField DataField="fname" HeaderText="First Name" ItemStyle-Width="55%" ItemStyle-Padding="2.5px" HeaderStyle-Padding="2.5px" HeaderStyle-Width="55%" /> <!-- 姓氏列 --> <asp:BoundField DataField="lname" HeaderText="Last Name" ItemStyle-Padding="2.5px" HeaderStyle-Padding="2.5px" /> <!-- 子GridView列 --> <asp:TemplateField HeaderText="Salary & Post"> <ItemTemplate> <asp:GridView ID="GridView2" runat="server" Width="99%" GridLines="Both" AutoGenerateColumns="false" CssClass="ChildGrid"> <Columns> <asp:BoundField DataField="salary" HeaderText="Salary" /> <asp:BoundField DataField="post" HeaderText="Post" /> </Columns> </asp:GridView> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </div> </form> </body>
2. 修正后台代码的子GridView数据获取逻辑
从当前数据行的绑定数据中获取idemp值,并使用参数化查询避免SQL注入:
namespace WebApplication2 { public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { bindGridview(); } } public void bindGridview() { DataTable dt = new DataTable(); string constr = @"server=127.0.0.1;user id=root;pwd=n0711p2010p;database=emp"; using (MySqlConnection con = new MySqlConnection(constr)) { MySqlCommand cmd = new MySqlCommand("SELECT idemp, fname, lname FROM emp", con); con.Open(); using (MySqlDataReader dtreader = cmd.ExecuteReader()) { dt.Load(dtreader); } if (dt.Rows.Count > 0) { GridView1.DataSource = dt; GridView1.DataBind(); } } } protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // 从当前数据行获取真实的idemp值 DataRowView rowView = (DataRowView)e.Row.DataItem; int empId = Convert.ToInt32(rowView["idemp"]); DataTable dt = new DataTable(); string constr = @"server=127.0.0.1;user id=root;pwd=n0711p2010p;database=emp"; using (MySqlConnection con = new MySqlConnection(constr)) { con.Open(); // 参数化查询,避免SQL注入并保证数据准确性 MySqlCommand cmd = new MySqlCommand("SELECT salary, post FROM emp WHERE idemp = @EmpId", con); cmd.Parameters.AddWithValue("@EmpId", empId); using (MySqlDataReader dtreader = cmd.ExecuteReader()) { dt.Load(dtreader); } GridView childGrid = (GridView)e.Row.FindControl("GridView2"); if (dt.Rows.Count > 0) { childGrid.DataSource = dt; childGrid.DataBind(); } } } } } }
关键改进点总结
- 让表头列与数据列一一对应,避免单独用
TemplateField包裹整个表头。 - 为子
GridView明确配置列,确保数据正常渲染。 - 使用参数化查询获取子表数据,既保证数据准确性(不再依赖行索引),又避免SQL注入风险。
- 优化资源释放:用
using语句自动释放MySqlDataReader等资源。
内容的提问来源于stack exchange,提问作者nisarg parekh
相关产品推荐
相关产品推荐

