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

ASP.NET C#:GridView动态添加行二次点击数据丢失问题求助

解决GridView二次点击按钮初始行被清空的问题

问题根源

每次页面回发(如点击生成数据按钮)时,未持久化GridView的数据源。默认情况下,回发后会重新创建数据源并绑定,导致之前添加的行被覆盖。需将数据源存储在ViewState或Session中,保留历史数据。

修正后的.aspx标记代码

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>GridView数据处理</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="txtNumber" runat="server" PlaceHolder="输入乘数"></asp:TextBox>
            <asp:DropDownList ID="ddlMultiplier" runat="server">
                <asp:ListItem Text="2" Value="2"></asp:ListItem>
                <asp:ListItem Text="3" Value="3"></asp:ListItem>
                <asp:ListItem Text="4" Value="4"></asp:ListItem>
            </asp:DropDownList>
            <asp:Button ID="btnGenerate" runat="server" Text="生成多行数据" OnClick="btnGenerate_Click" />
            <asp:Button ID="btnSave" runat="server" Text="保存修改" OnClick="btnSave_Click" />
            <br /><br />
            <asp:GridView ID="gvData" runat="server" AutoGenerateColumns="False" OnRowEditing="gvData_RowEditing" OnRowUpdating="gvData_RowUpdating" OnRowCancelingEdit="gvData_RowCancelingEdit">
                <Columns>
                    <asp:BoundField DataField="OriginalNumber" HeaderText="原始数字" />
                    <asp:BoundField DataField="Multiplier" HeaderText="乘数" />
                    <asp:TemplateField HeaderText="结果">
                        <ItemTemplate>
                            <asp:Label ID="lblResult" runat="server" Text='<%# Eval("Result") %>'></asp:Label>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:TextBox ID="txtResult" runat="server" Text='<%# Eval("Result") %>'></asp:TextBox>
                        </EditItemTemplate>
                    </asp:TemplateField>
                    <asp:CommandField ShowEditButton="True" />
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>

修正后的C#后台代码

using System;
using System.Data;

public partial class _Default : System.Web.UI.Page
{
    private const string DataTableViewStateKey = "GridViewData";

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("OriginalNumber", typeof(int));
            dt.Columns.Add("Multiplier", typeof(int));
            dt.Columns.Add("Result", typeof(int));
            ViewState[DataTableViewStateKey] = dt;
            gvData.DataSource = dt;
            gvData.DataBind();
        }
    }

    protected void btnGenerate_Click(object sender, EventArgs e)
    {
        DataTable dt = (DataTable)ViewState[DataTableViewStateKey];
        
        int originalNumber;
        int multiplier;
        if (int.TryParse(txtNumber.Text, out originalNumber) && int.TryParse(ddlMultiplier.SelectedValue, out multiplier))
        {
            for (int i = 1; i <= multiplier; i++)
            {
                DataRow dr = dt.NewRow();
                dr["OriginalNumber"] = originalNumber;
                dr["Multiplier"] = i;
                dr["Result"] = originalNumber * i;
                dt.Rows.Add(dr);
            }
            
            ViewState[DataTableViewStateKey] = dt;
            gvData.DataSource = dt;
            gvData.DataBind();
            txtNumber.Text = string.Empty;
        }
    }

    protected void btnSave_Click(object sender, EventArgs e)
    {
        DataTable dt = (DataTable)ViewState[DataTableViewStateKey];
        foreach (GridViewRow row in gvData.Rows)
        {
            if (row.RowType == DataControlRowType.DataRow)
            {
                int rowIndex = row.DataItemIndex;
                TextBox txtResult = row.FindControl("txtResult") as TextBox;
                if (txtResult != null)
                {
                    int result;
                    if (int.TryParse(txtResult.Text, out result))
                    {
                        dt.Rows[rowIndex]["Result"] = result;
                    }
                }
            }
        }
        ViewState[DataTableViewStateKey] = dt;
        // 此处可添加数据持久化到数据库的逻辑
        Response.Write("修改已保存");
    }

    protected void gvData_RowEditing(object sender, GridViewEditEventArgs e)
    {
        gvData.EditIndex = e.NewEditIndex;
        gvData.DataSource = (DataTable)ViewState[DataTableViewStateKey];
        gvData.DataBind();
    }

    protected void gvData_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        DataTable dt = (DataTable)ViewState[DataTableViewStateKey];
        GridViewRow row = gvData.Rows[e.RowIndex];
        TextBox txtResult = row.FindControl("txtResult") as TextBox;
        if (txtResult != null)
        {
            int result;
            if (int.TryParse(txtResult.Text, out result))
            {
                dt.Rows[e.RowIndex]["Result"] = result;
            }
        }
        gvData.EditIndex = -1;
        ViewState[DataTableViewStateKey] = dt;
        gvData.DataSource = dt;
        gvData.DataBind();
    }

    protected void gvData_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        gvData.EditIndex = -1;
        gvData.DataSource = (DataTable)ViewState[DataTableViewStateKey];
        gvData.DataBind();
    }
}

关键修正点

  • 持久化数据源:使用ViewState存储DataTable,确保页面回发时保留历史数据,避免每次点击按钮重新创建数据源导致旧数据丢失。
  • 追加数据逻辑:点击生成按钮时,先从ViewState取出已有DataTable,再添加新行,而非重新初始化。
  • 编辑同步:编辑和保存操作时,同步更新ViewState中的DataTable,保证数据一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:00:56