ASP.NET C#:如何通过代码设置无数据源GridView的列为只读?
GridView 指定列设为只读无效的解决方法
问题背景
使用无数据源绑定的GridView,通过下拉列表切换显示不同数据表,仅希望1-2列可编辑,其余列设为只读,但尝试多种方案均未生效。
尝试过的无效代码
RowDataBound 事件实现
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { //// 此方法无效 BoundField bound = GridView1.Columns[0] as BoundField; bound.InsertVisible = false; bound.ReadOnly = true; }
RowUpdating 事件实现
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e) { ((BoundField)GridView1.Columns[1]).ReadOnly = true;//此方法也无效 GridViewRow row = GridView1.Rows[e.RowIndex]; string contract_ID = (row.Cells[2].Controls[0] as TextBox).Text; string room_ID= (row.Cells[6].Controls[0] as TextBox).Text; string query = "UPDATE CONTRACTE_INCHIRIERE SET ID_CAMERA='"+room_ID+"' WHERE ID_CONTRACT="+contract_ID; Response.Write(query); using (OracleCommand cmd = new OracleCommand(query,con)) { con.Open(); cmd.ExecuteNonQuery(); con.Close(); } //重置编辑索引 GridView1.EditIndex = -1; //绑定GridView数据 SortingBindGrid(); }
问题截图


有效解决方案
方法1:针对编辑行单独设置控件状态
直接修改列的ReadOnly属性会被动态数据源绑定覆盖,正确做法是在RowDataBound中判断当前行是否为编辑行,再将对应单元格的输入控件设为只读/禁用:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { // 仅处理编辑状态的行 if ((e.Row.RowState & DataControlRowState.Edit) != 0) { // 将第0列设为只读 TextBox txtCol0 = e.Row.Cells[0].Controls[0] as TextBox; if (txtCol0 != null) { txtCol0.ReadOnly = true; txtCol0.Enabled = false; // 可选:彻底禁用防止焦点选中 } // 将第1列设为只读 TextBox txtCol1 = e.Row.Cells[1].Controls[0] as TextBox; if (txtCol1 != null) { txtCol1.ReadOnly = true; txtCol1.Enabled = false; } } }
方法2:动态生成列时直接设置只读属性
因为是切换不同数据表动态绑定,可在创建BoundField时直接指定ReadOnly,避免后续被覆盖:
// 示例:动态生成只读列 BoundField contractIdCol = new BoundField(); contractIdCol.DataField = "ID_CONTRACT"; contractIdCol.HeaderText = "合同ID"; contractIdCol.ReadOnly = true; // 直接标记为只读 GridView1.Columns.Add(contractIdCol); // 可编辑列示例 BoundField roomIdCol = new BoundField(); roomIdCol.DataField = "ID_CAMERA"; roomIdCol.HeaderText = "房间ID"; roomIdCol.ReadOnly = false; GridView1.Columns.Add(roomIdCol);
方法3:更新时忽略只读列的输入值
如果前端仍能修改,可在RowUpdating中直接取只读列的原始文本(而非输入控件值),仅处理允许编辑的列:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e) { GridViewRow row = GridView1.Rows[e.RowIndex]; // 只读列直接取单元格文本,而非TextBox值 string contract_ID = row.Cells[2].Text; string room_ID= (row.Cells[6].Controls[0] as TextBox).Text; // 替换为参数化查询,避免SQL注入 string query = "UPDATE CONTRACTE_INCHIRIERE SET ID_CAMERA=:roomId WHERE ID_CONTRACT=:contractId"; using (OracleCommand cmd = new OracleCommand(query, con)) { cmd.Parameters.Add(":roomId", OracleDbType.Varchar2).Value = room_ID; cmd.Parameters.Add(":contractId", OracleDbType.Varchar2).Value = contract_ID; con.Open(); cmd.ExecuteNonQuery(); con.Close(); } GridView1.EditIndex = -1; SortingBindGrid(); }
关键说明
- 原方法失效原因:直接修改
GridView.Columns[x].ReadOnly会在动态切换数据源时被重置,因为每次绑定会重新生成列配置。 - 务必使用参数化查询替换字符串拼接,避免SQL注入风险。
内容的提问来源于stack exchange,提问作者Tudor Octavian
相关产品推荐
相关产品推荐

