在GridView中停止文本框在回发时丢失数据

时间:2014-03-27 10:49:15

标签: asp.net gridview postback

我有一个GridView,它通过button_OnClick事件动态添加行,这会添加一个带有Product name&的新行。 DropDownList中的产品ID,还包含一个带有用于用户输入的空文本框的列。

我的问题是,当我测试它并在文本框中输入数据,然后添加另一个产品时,回发导致我的数据丢失(正确的行数仍然存在产品名称/ ids)。

                            <asp:GridView runat="server" ID="grdSelectedProducts" BorderWidth="1px" CellPadding="3" CellSpacing="2" AutoGenerateColumns="False" OnRowDataBound="grdSelectedProducts_OnRowDataBound" ShowHeaderWhenEmpty="True" DataKeyNames="ProductId"
                                OnRowCommand="grdSelectedProducts_RowCommand" OnRowDeleted="grdSelectedProducts_RowDeleted" OnRowDeleting="grdSelectedProducts_RowDeleting" EmptyDataText="Please select a Product and click 'Add'" EnableViewState="True">
                                <Columns>
                                    <asp:BoundField DataField="Product" HeaderText="Product" ReadOnly="False"/>
                                    <asp:TemplateField HeaderText="Description">
                                        <ItemTemplate>
                                                 <asp:TextBox runat="server" ID="txtDescriptionEntry" Text="" style="width:98% !important" EnableViewState="True"></asp:TextBox>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField>
                                        <ItemTemplate>
                                            <asp:LinkButton runat="server" ID="linkDelete" runat="server" CommandName="Delete" CommandArgument="<%# Container.DataItemIndex %>">Remove</asp:LinkButton>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:BoundField DataField="ProductId" HeaderText="ProductId" ReadOnly="False" Visible="False" />
                                </Columns>
                            </asp:GridView>

如何避免在创建的每个txtDescriptionEntry上回发报废数据?这些文本框可能介于0和无数之间,因此我在任何时候都没有确切的名称。

修改,根据下面的评论,我将包含有关如何向网格添加行的代码:         私有DataTable ProductDataTable         {             获取{return ViewState [&#34; ProductDataTable&#34;]作为DataTable ?? new DataTable(); }             设置{ViewState [&#34; ProductDataTable&#34;] = value; }         }

    private DataTable CreateDataTable(bool isAddingValue, string selectedProduct, string selectedId)
    {
        // if isAddingValue is FALSE then it isn't from a button click to add a Product, it is just
        // a call to create the datatable

        DataTable dataTable = ProductDataTable;
        if (!dataTable.Columns.Contains("Product"))
        {
            dataTable.Columns.Add("Product");
            dataTable.Columns.Add("Description"); // This column is free format text that the user enters.
            dataTable.Columns.Add("ProductId");
        }

        if (isAddingValue)
        {
            // Get the data from ViewState
            //dataTable = ProductDataTable;
            DataRow dataRow;
            dataRow = dataTable.NewRow();
            dataRow["Product"] = selectedProduct;
            dataRow["ProductId"] = selectedId;
            dataTable.Rows.Add(dataRow);
        }
        else
        {
            grdSelectedProducts.DataSource = null;
            grdSelectedProducts.DataSource = ProductDataTable;
            grdSelectedProducts.DataBind();

        }
        // Save the data back to ViewState
        ProductDataTable = dataTable;

        return dataTable;
    }

    protected void btnAddProduct_OnClick(object sender, EventArgs e)
    {
        string selectedProduct = ddlProduct.SelectedItem.Text;
        string selectedId = ddlProduct.SelectedValue;

        DataTable dataTable = CreateDataTable(true, selectedProduct, selectedId);

        grdSelectedProducts.DataSource = dataTable;
        grdSelectedProducts.DataBind();

    }

    protected void grdSelectedProducts_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        if (e.CommandName == "Delete")
        {
            if (!string.IsNullOrEmpty(e.CommandArgument.ToString()))
            {
                int rowIndex = Convert.ToInt32(e.CommandArgument);
                DataTable table = CreateDataTable(false, string.Empty, string.Empty);
                table.Rows.RemoveAt(rowIndex);
                grdSelectedProducts.DataSource = table;
                grdSelectedProducts.DataBind();
            }
        }
    }

在Page_Load事件中,如果它不是PostBack,那么还会绑定一个空列表

        grdSelectedProducts.DataSource = new List<Products>();
        grdSelectedProducts.DataBind();

1 个答案:

答案 0 :(得分:0)

我想出了这个,不是最好的解决方案(所以我可能不会推荐它)但它让我摆脱了堵塞。

我使用了OnRowDataBound事件,因此对于绑定到表的每一行,我会使用RowIndex来获取DataTable中的相应行,然后我会分配文本框(也通过索引获得)来自DT的值。示例如下。

    protected void grdSelectedproducts_OnRowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowIndex > -1)
        {
            TextBox txtDescription = e.Row.FindControl("txtDescriptionEntry") as TextBox;

            if (txtDescription != null)
            {
                DataTable dt = ProductDataTable;
                DataRow row = dt.Rows[e.Row.RowIndex] as DataRow;
                txtDescription.Text = row[1].ToString();
            }
        }
    }