C# 表中动态创建的文本框丢失了文本值
我有一个动态生成的表,在2列中有文本框。在回发过程中,文本框总是空的,即使我填充了它们。 该表的构建方式如下:C# 表中动态创建的文本框丢失了文本值,c#,asp.net,textbox,C#,Asp.net,Textbox,我有一个动态生成的表,在2列中有文本框。在回发过程中,文本框总是空的,即使我填充了它们。 该表的构建方式如下: protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e) { DataTable dtRighe = oTab.getScaleTaglieRighe(ddlScalaTaglie.SelectedValue); //dt is datata
protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtRighe = oTab.getScaleTaglieRighe(ddlScalaTaglie.SelectedValue);
//dt is datatable object which holds DB results.
Table tbl = new Table();
tbl.CssClass = "table table-striped table-bordered table-responsive";
TableRow tr;
TableCell tcEU, tcUS, tcUK, tcQty, tcEAN;
Label lbEU, lbUS, lbUK, lbQty, lbEAN;
TextBox tbEU, tbUS, tbUK, tbQty, tbEAN, tbToFocus = null;
foreach (DataRow dr in dtRighe.Rows)
{
tr = new TableRow();
//ean
tcEAN = new TableCell();
tbEAN = new TextBox();
tbEAN.ID = "txtEAN" + dr[0].ToString();
tbEAN.Width = new Unit(100, UnitType.Percentage);
tbEAN.Columns = 15;
tcEAN.Controls.Add(tbEAN);
tr.Controls.Add(tcEAN);
//Qty
tcQty = new TableCell();
tbQty = new TextBox();
tbQty.ID = "txtQty" + dr[0].ToString();
tbQty.TextMode = TextBoxMode.Number;
tcQty.Controls.Add(tbQty);
tr.Controls.Add(tcQty);
tbl.Controls.Add(tr);
}
Session["tbl"] = tbl;
divTaglieRighe.Controls.Add(tbl);
}
当我点击“保存”按钮时,我必须在表格中循环并保存所有文本框。文本
这是我写的:
ArrayList arrScarpaFigli = new ArrayList();
Table tbl = (Table)Session["tbl"];
foreach (TableRow row in tbl.Rows)
{
foreach (TableCell cell in row.Cells)
{
foreach (Control ctrl in cell.Controls)
{
//CONTROL IS TEXBOXT: EXTRACT VALUES//
if (ctrl is TextBox)
{
TextBox txt = (TextBox)ctrl;
arrScarpaFigli.Add(txt.Text);
}
}
}
}
问题是,如果我填写文本框,文本中总是有一个空字符串。
我填写表格的唯一时刻是在下拉列表的selectionChange上
我做错了什么?
提前感谢在
会话
中存储表
控件的实例是一个糟糕的想法,完全是错误的。控件属于它们的父页-它们应该在创建后立即添加到父页中,并且应该随父页一起消失
ASP.NET中动态创建的控件的问题是,您必须存储它们被创建的事实的指示器(以及再次创建它们所需的相关信息),并在所有后续回发中重新创建它们-不迟于Page\u Load
。只有这样,这些控件才有机会从Request
获取它们的值,而您也有机会从控件获取这些值
在您的代码中,存储在会话
中的表
的实例(及其所有行、单元格和文本框)永远不会反映任何客户端数据更改,也不会属于为处理后续回发请求而创建的页
更新
这里需要了解的一个重要事实是,在处理由ddlScalaTaglie
更改引起的回发并将hew html返回给客户端之后,页面实例就消失了。在下一个请求中,将创建页面的一个新实例,但它不知道上一个实例的控制树中添加了表这一事实。您在Page\u Load
中的代码必须发现表单必须具有此表,并以与第一次创建时完全相同的方式创建表-行、单元格和文本框具有完全相同的ID
s
然后,将这个新创建的表添加到
divTaglieRighe.Controls
之后,文本框将能够从Request.Form
集合中提取它们的客户端值。在会话中存储表
控件的实例是一个糟糕的想法,完全是错误的。控件属于它们的父页-它们应该在创建后立即添加到父页中,并且应该随父页一起消失
ASP.NET中动态创建的控件的问题是,您必须存储它们被创建的事实的指示器(以及再次创建它们所需的相关信息),并在所有后续回发中重新创建它们-不迟于Page\u Load
。只有这样,这些控件才有机会从Request
获取它们的值,而您也有机会从控件获取这些值
在您的代码中,存储在会话
中的表
的实例(及其所有行、单元格和文本框)永远不会反映任何客户端数据更改,也不会属于为处理后续回发请求而创建的页
更新
这里需要了解的一个重要事实是,在处理由ddlScalaTaglie
更改引起的回发并将hew html返回给客户端之后,页面实例就消失了。在下一个请求中,将创建页面的一个新实例,但它不知道上一个实例的控制树中添加了表这一事实。您在Page\u Load
中的代码必须发现表单必须具有此表,并以与第一次创建时完全相同的方式创建表-行、单元格和文本框具有完全相同的ID
s
然后,将这个新创建的表添加到divtaglierghe.Controls
,文本框将能够从Request.Form
集合中提取其客户端值。您创建了一个名为tbl
的表,并添加了两个TextBox
,然后将表控件存储在会话session[“tbl”]
并添加到divtaglier控件中。最后,您试图从会话session[“tbl”]
表中获取文本框数据,而不是添加在divTaglieRighe
控件中的ViewState控件。您必须从表tbl
控件中获取数据,该控件添加到divTaglieRighe
控件中。您已经创建了一个名为tbl
的表,并添加了两个文本框
,然后您将表控件存储在会话会话[“tbl”
中,并添加到divTaglieRighe
控件中。最后,您试图从会话session[“tbl”]
表中获取文本框数据,而不是添加在divTaglieRighe
控件中的ViewState控件。您必须从表tbl
控件中获取数据,该控件添加到divTaglieRighe
控件中。您必须在每次页面加载时重新创建动态控件,以确保回发后保留其值。因此,您需要创建一个新方法,在每次加载页面时处理表的创建
protected void Page_Load(object sender, EventArgs e)
{
//always create the controls on every page load if there is a value selected in ddlScalaTaglie
if (!string.IsNullOrEmpty(ddlScalaTaglie.SelectedValue))
{
createTable(ddlScalaTaglie.SelectedValue);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
//use findcontrol to find the Table inside the placeholder
Table tbl = Page.FindControl("divTaglieRighe").FindControl("Table1") as Table;
//loop all rows and cells in the Table
foreach (TableRow row in tbl.Rows)
{
foreach (TableCell cell in row.Cells)
{
foreach (Control ctrl in cell.Controls)
{
//the control is a textbox
if (ctrl is TextBox)
{
//cast the control back to a textbox
TextBox tb = ctrl as TextBox;
//does the checkbox have a value, if so append the label
if (!string.IsNullOrEmpty(tb.Text))
{
Label1.Text += tb.Text + "<br>";
}
}
}
}
}
}
protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
{
//no need to create the Table dynamically, that will be handled in Page_Load
//this method is just a dummy to trigger a PostBack
//you could remove this method and the OnSelectedIndexChanged from the DropDown
//and just keep the AutoPostBack="true", that will also work
}
private void createTable(string value)
{
DataTable dtRighe = Common.LoadFromDB();
//create a new table WITH id, that is needed for findcontrol
Table tbl = new Table();
tbl.ID = "Table1";
//loop all rows in the datatable
foreach (DataRow dr in dtRighe.Rows)
{
TableRow tr = new TableRow();
//ean
TableCell tcEAN = new TableCell();
TextBox tbEAN = new TextBox();
tbEAN.ID = "txtEAN" + dr[0].ToString();
tbEAN.Width = new Unit(100, UnitType.Percentage);
tbEAN.Columns = 15;
tcEAN.Controls.Add(tbEAN);
tr.Controls.Add(tcEAN);
//Qty
TableCell tcQty = new TableCell();
TextBox tbQty = new TextBox();
tbQty.ID = "txtQty" + dr[0].ToString();
tbQty.TextMode = TextBoxMode.Number;
tcQty.Controls.Add(tbQty);
tr.Controls.Add(tcQty);
tbl.Controls.Add(tr);
}
//add the table to the placeholder
divTaglieRighe.Controls.Add(tbl);
}
受保护的无效页面加载(对象发送方,事件参数e)
{
//如果在ddlScalaTaglie中选择了值,则始终在每次页面加载时创建控件
如果(!string.IsNullOrEmpty(ddlScalaTaglie.SelectedValue))
{
createTable(ddlScalaTaglie.SelectedValue);
}
}
受保护的无效按钮1\u单击(对象发送者,事件参数e)
{
//使用findcontrol查找占位符内的表
表tbl=第页FindControl(“divTaglieRighe”)。FindControl(“表1”)为表;
//循环表中的所有行和单元格
<asp:DropDownList ID="ddlScalaTaglie" runat="server" OnSelectedIndexChanged="ddlScalaTaglie_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Text="Select..." Value=""></asp:ListItem>
<asp:ListItem Text="Option 1" Value="1"></asp:ListItem>
<asp:ListItem Text="Option 2" Value="2"></asp:ListItem>
</asp:DropDownList>
<br />
<br />
<asp:PlaceHolder ID="divTaglieRighe" runat="server"></asp:PlaceHolder>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Save" OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>