You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
}

问题截图

GridView编辑状态截图1
GridView编辑状态截图2

有效解决方案

方法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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:16:01