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

.NET 4.7 WebForms无数据库GridView做CRUD报RowUpdating事件未处理错误

问题根因

这个报错的核心原因是GridView事件绑定模式和实现逻辑不匹配:

  • 你配置的UpdateMethod是ASP.NET 4.5引入的强类型Model Binding模式专属属性,仅在通过SelectMethod配置数据源查询方法时才会自动触发
  • 你当前使用的是手动赋值DataSource+调用DataBind()的传统绑定模式,这种模式下点击更新按钮时,GridView会直接触发RowUpdating行事件,你没有绑定对应的OnRowUpdating事件处理方法,就会抛出“事件未处理”的错误。

现有代码还存在几个会导致CRUD功能失效的问题:

  • 未给GridView配置DataKeyNames属性指定主键字段,更新、删除时无法获取行对应的主键值
  • GView_RowEditing事件方法为空,没有实际执行切换编辑索引、重新绑定数据的逻辑
  • 未绑定RowCancelingEdit(取消编辑)、RowDeleting(删除)事件,点击对应按钮时也会抛出同类未处理事件错误
  • Page_Load没有处理首次加载的数据绑定逻辑,内存数据无法正常加载到控件

修复方案1:传统绑定模式(改造成本最低)

不需要改动现有内存List存储逻辑,补全事件绑定和对应处理方法即可。

  1. 修改前端GridView控件配置,补全事件绑定、主键配置,移除无效的UpdateMethod属性:
<asp:GridView runat="server" ID="GView" CellPadding="4" ForeColor="#333333" GridLines="None"
    DataKeyNames="Id"
    OnRowEditing="GView_RowEditing"
    OnRowCancelingEdit="GView_RowCancelingEdit"
    OnRowUpdating="GView_RowUpdating"
    OnRowDeleting="GView_RowDeleting"
    AutoGenerateColumns="True">
    <AlternatingRowStyle BackColor="White"></AlternatingRowStyle>
    <Columns>
        <asp:CommandField ShowEditButton="True" ShowDeleteButton="True"></asp:CommandField>
    </Columns>
</asp:GridView>
  1. 补全后端事件逻辑,修正数据绑定逻辑:
protected void Page_Load(object sender, EventArgs e)
{
    // 仅首次页面加载时绑定数据,回发场景不重复绑定,避免覆盖编辑状态
    if (!IsPostBack)
    {
        BindGrid();
    }
}

// 抽离统一绑定方法,减少重复代码
private void BindGrid()
{
    GView.DataSource = contatos;
    GView.DataBind();
}

public static List<Contato> contatos = new List<Contato>();

public void btnCad(object sender, EventArgs e)
{
    Contato contato = new Contato();
    // 注意:用Count作为自增Id在删除数据后会出现Id重复问题,仅适合测试场景
    contato.Id = contatos.Count;
    contato.Nome = this.txtNome.Text;
    contato.Idade = this.txtIdade.Text;
    contato.Telefone = this.txtTelefone.Text;
    contato.Genero = this.txtGenero.Text;
    contato.DataCadastro = this.txtDataCad.Text;

    contatos.Add(contato);
    BindGrid();
}

// 切换行编辑状态
protected void GView_RowEditing(object sender, GridViewEditEventArgs e)
{
    GView.EditIndex = e.NewEditIndex;
    BindGrid();
}

// 取消编辑
protected void GView_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
    GView.EditIndex = -1;
    BindGrid();
}

// 处理更新逻辑
protected void GView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    // 从DataKey中获取当前行主键
    int id = Convert.ToInt32(GView.DataKeys[e.RowIndex].Value);
    Contato item = contatos.Find(cont => cont.Id == id);
    if (item == null) return;

    // 从编辑行的输入控件中取新值,注意单元格索引按实际列顺序调整:前两列为命令按钮列,业务字段从第3列(索引2)开始
    item.Nome = (GView.Rows[e.RowIndex].Cells[2].Controls[0] as TextBox)?.Text;
    item.Idade = (GView.Rows[e.RowIndex].Cells[3].Controls[0] as TextBox)?.Text;
    item.Telefone = (GView.Rows[e.RowIndex].Cells[4].Controls[0] as TextBox)?.Text;
    item.Genero = (GView.Rows[e.RowIndex].Cells[5].Controls[0] as TextBox)?.Text;
    item.DataCadastro = (GView.Rows[e.RowIndex].Cells[6].Controls[0] as TextBox)?.Text;

    // 退出编辑状态,刷新数据
    GView.EditIndex = -1;
    BindGrid();
}

// 处理删除逻辑
protected void GView_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    int id = Convert.ToInt32(GView.DataKeys[e.RowIndex].Value);
    Contato item = contatos.Find(cont => cont.Id == id);
    if (item != null)
    {
        contatos.Remove(item);
    }
    BindGrid();
}

修复方案2:Model Binding模式(适配原有UpdateMethod写法)

如果要使用你之前写的UpdateMethod、TryUpdateModel的简化写法,就用Model Binding模式,不需要手动从单元格取控件值。

  1. 修改前端GridView配置,补全绑定方法配置:
<asp:GridView runat="server" ID="GView" CellPadding="4" ForeColor="#333333" GridLines="None"
    DataKeyNames="Id"
    SelectMethod="GView_GetData"
    UpdateMethod="GView_UpdateItem"
    DeleteMethod="GView_DeleteItem"
    AutoGenerateColumns="True">
    <AlternatingRowStyle BackColor="White"></AlternatingRowStyle>
    <Columns>
        <asp:CommandField ShowEditButton="True" ShowDeleteButton="True"></asp:CommandField>
    </Columns>
</asp:GridView>
  1. 后端实现对应绑定方法,不需要手动调用DataBind:
protected void Page_Load(object sender, EventArgs e)
{
    // Model Binding模式自动处理数据绑定,不需要手动写绑定逻辑
}

public static List<Contato> contatos = new List<Contato>();

// SelectMethod:返回GridView需要绑定的全量数据
public List<Contato> GView_GetData()
{
    return contatos;
}

public void btnCad(object sender, EventArgs e)
{
    Contato contato = new Contato();
    contato.Id = contatos.Count;
    contato.Nome = this.txtNome.Text;
    contato.Idade = this.txtIdade.Text;
    contato.Telefone = this.txtTelefone.Text;
    contato.Genero = this.txtGenero.Text;
    contato.DataCadastro = this.txtDataCad.Text;
    contatos.Add(contato);
}

// 原有更新方法可直接生效,TryUpdateModel自动完成输入值到实体的映射
public void GView_UpdateItem(int id)
{
    Contato item = contatos.Find(cont => cont.Id == id);
    if (item == null)
    {
        ModelState.AddModelError("", String.Format("O item com id {0} não foi encontrado", id));
        return;
    }
    TryUpdateModel(item);
    if (ModelState.IsValid)
    {
        // 更新成功后控件自动刷新数据,不需要手动绑定
    }
}

// 删除方法
public void GView_DeleteItem(int id)
{
    Contato item = contatos.Find(cont => cont.Id == id);
    if (item != null)
    {
        contatos.Remove(item);
    }
}

注意:使用static List<Contato>存储数据时,所有访问站点的用户会共享同一份数据,且应用程序池重启后数据会全部丢失,仅适合本地功能测试,不能直接用于生产环境。

内容的提问来源于stack exchange,提问作者lucasmenchon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:27:47