GridView的OnDataBound与OnPreRender事件用途及列修改方法问询
GridView的OnDataBound/OnPreRender事件使用问题解答
问题背景
从数据库查询数据绑定到GridView,通过OnRowDataBound事件格式化数字等内容。结果集中包含用于排序的orderby列,需要将其从GridView中隐藏:
- 自动生成列时,可在
OnRowDataBound中设置Header和DataRow对应的单元格Visible=false实现隐藏; - 非自动生成列时,在.aspx中设置
Hidden="true"无效,且不想通过.aspx页面处理; - 尝试用
OnDataBound和OnPreRender事件更新GridView(隐藏列、创建总计行)时,发现gridView.Columns.Count为0(虽有数据),无法实现; - 当前可通过
OnRowDataBound实现需求,但该方法需逐行逐列处理,复杂页面会产生冗长代码。
疑问解答
1. OnDataBound和OnPreRender事件能否更新GridView?可以,示例如下
你遇到Columns.Count=0的原因是:当GridView未在.aspx中显式声明<Columns>节点时,Columns集合不会被填充——只有显式定义列时,Columns集合才会有数据。自动生成列或通过数据源绑定但未显式列的场景下,需通过HeaderRow和Rows的Cells集合来操作列。
OnDataBound事件示例(隐藏orderby列+添加总计行)
protected void checks_DataBound(object sender, EventArgs e) { GridView gridView = (GridView)sender; if (gridView.ClientID != "checks_db_sod01") return; // 定位orderby列的索引 int orderByColIndex = -1; if (gridView.HeaderRow != null) { for (int i = 0; i < gridView.HeaderRow.Cells.Count; i++) { if (gridView.HeaderRow.Cells[i].Text.ToLower().Trim() == "orderby") { orderByColIndex = i; gridView.HeaderRow.Cells[i].Visible = false; break; } } } // 隐藏所有数据行的对应列 if (orderByColIndex != -1) { foreach (GridViewRow row in gridView.Rows) { if (row.RowType == DataControlRowType.DataRow) { row.Cells[orderByColIndex].Visible = false; } } } // 额外示例:添加总计行 GridViewRow totalRow = new GridViewRow(0, 0, DataControlRowType.Footer, DataControlRowState.Normal); // 合并前n-1列单元格显示"总计" totalRow.Cells.Add(new TableHeaderCell { Text = "总计", ColumnSpan = gridView.HeaderRow.Cells.Count - 1 }); // 计算最后一列的数值总和 decimal totalAmount = 0; foreach (GridViewRow row in gridView.Rows) { if (row.RowType == DataControlRowType.DataRow) { if (decimal.TryParse(row.Cells[gridView.HeaderRow.Cells.Count - 1].Text, out decimal amount)) { totalAmount += amount; } } } totalRow.Cells.Add(new TableHeaderCell { Text = totalAmount.ToString("N2") }); gridView.Controls[0].Controls.Add(totalRow); }
OnPreRender事件示例(隐藏orderby列+设置行样式)
protected void checks_PreRender(object sender, EventArgs e) { GridView gridView = (GridView)sender; if (gridView.ClientID != "checks_db_sod01") return; // 定位orderby列的索引 int orderByColIndex = -1; if (gridView.HeaderRow != null) { for (int i = 0; i < gridView.HeaderRow.Cells.Count; i++) { if (gridView.HeaderRow.Cells[i].Text.ToLower().Trim() == "orderby") { orderByColIndex = i; break; } } } // 隐藏该列的所有单元格(表头、数据行、页脚) if (orderByColIndex != -1) { gridView.HeaderRow.Cells[orderByColIndex].Visible = false; foreach (GridViewRow row in gridView.Rows) { row.Cells[orderByColIndex].Visible = false; } if (gridView.FooterRow != null) { gridView.FooterRow.Cells[orderByColIndex].Visible = false; } } // 额外示例:给奇数行设置背景色 foreach (GridViewRow row in gridView.Rows) { if (row.RowType == DataControlRowType.DataRow && row.RowIndex % 2 == 1) { row.BackColor = System.Drawing.Color.LightGray; } } }
2. OnDataBound和OnPreRender事件的用途
OnDataBound事件
- 触发时机:GridView完成所有数据绑定(所有行已生成并绑定数据)后立即触发。
- 核心用途:
- 对绑定后的数据集进行批量处理,如计算总计、统计数据;
- 基于绑定数据调整行/列属性,如格式化数据、隐藏特定行/列;
- 数据绑定后的验证或二次加工,如根据数据值设置行样式、显示状态。
- 特点:此时GridView的行已全部生成,但未进入渲染阶段,适合做基于数据的逻辑处理。
OnPreRender事件
- 触发时机:GridView即将渲染到页面之前,是控件生命周期中最后一个可修改控件属性的阶段。
- 核心用途:
- 做最终的UI调整,如修改控件样式、列可见性、行样式;
- 处理依赖控件最终状态的逻辑,如根据页面其他控件状态调整GridView;
- 动态添加/移除控件元素,如添加自定义按钮、调整列顺序。
- 特点:此时控件的布局和数据已完全确定,适合做渲染前的最终修正。
内容的提问来源于stack exchange,提问作者ghbcode
相关产品推荐
相关产品推荐

