我有一个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();
答案 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();
}
}
}