我在动态创建的TextBox中遇到了这个问题。
在PageLoad中创建TextBox时,会触发TextChanged事件 但是当我动态删除并重新创建TextBox时,TextChanged没有被触发。
这是代码:
.aspx文件
<body>
<form id="form1" runat="server">
<div>
<asp:Table ID="Table1" runat="server">
<asp:TableRow>
<asp:TableCell ColumnSpan="2">Fixed content</asp:TableCell>
</asp:TableRow>
</asp:Table>
</form>
</body>
.cs文件
public partial class test : System.Web.UI.Page
{
string myText = "a";
protected void Page_Load(object sender, EventArgs e)
{
WriteRows();
}
private void WriteRows()
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TextBox txt = new TextBox();
txt.Text = myText;
txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler
tc.Controls.Add(txt);
tr.Controls.Add(tc);
tc = new TableCell();
tc.Text = txt.Text;
tr.Controls.Add(tc);
Table1.Controls.AddAt(1, tr);
}
private void txt_TextChanged(object sender, EventArgs e)
{
myText = ((TextBox)sender).Text;
RedrawTable(); // Delete the row (incl. the TextBox) and rewrite it
}
private void RedrawTable()
{
Table1.Controls.RemoveAt(1);
WriteRows();
}
}
是否有人有解决方案以便始终触发事件?
答案 0 :(得分:11)
事件处理由ASP.NET完成,匹配控件的ID&amp;请求参数。在您的情况下,在txtTextChanged()期间创建的TextBox将具有自动ID,因为您没有指定任何显式ID。该ID将在文本更改事件期间回发。
在页面加载事件之后,ASP.NET将尝试查找具有此类ID的控件以为其触发事件。显然,ASP.NET无法找到匹配项,因为在Page_Load()期间创建的TextBox是不同的,并且具有不同的ID。
要解决此问题:为文本框指定显式ID:
TextBox txt = new TextBox();
txt.Text = myText;
txt.ID = "txtBox";
答案 1 :(得分:3)
尝试在Page_Init()方法中创建控件......
答案 2 :(得分:2)
要触发的回发事件,应该触发事件的控件需要在回发生命周期中具有相同ID 和相同数据的。
如果您有静态控件(在您的aspx / ascx / master中定义)并且viewstate已打开,那么它们将自动重新创建。
如果您不想使用viewstate或使用动态控件,则需要在每个page_load 上对控件进行数据绑定,以便控件启动并及时运行以触发事件(发生在Page_load之后
如果更改父控件或页面的ID,则可能会意外丢弃viewstate autobind,因为控件ID包含祖先ID。我认为你应该安全地做到这一点,只要你在Page_Init(在设置viewstate之前)这样做了
答案 3 :(得分:2)
在Page_Init中重新创建动态创建的控件。如果在Page_Load中重新创建控件的viewstate数据,则无法访问该控件的viewstate数据(在PageLate加载到PreLoad中,该页面在Page_Load之前发生)。
另外,不要忘记为控件分配ID。
答案 4 :(得分:1)
我有类似的问题。我认为问题在于动态创建的控件不会保持在视图状态,并且不能在回发中存活。这是从我的代码中删除的评论,描述了我提出的解决方案(可能不是唯一的,但它对我有用)。
此页面用于动态定义网格。用户单击复选框 指示要包含在网格上的字段。这个页面的逻辑确实如此 两件必不可少的事情:
(1)它维护保存在ViewState中的GridDefinition对象。 (2)它重建了以编程方式添加的控件(基本上是一切 在表对象中)来自每个回发的ViewState中的GridDefinition。 动态添加的控件不会在ViewState的回发上重新创建。 实际上,我发现如果你不重新创建控件,他们的事件就不会触发。 显然:
"The process that matches controls to posted values occurs
after page_load completes, so it has to occur just like this
if you are to use this way."
当我收到控制事件表明数据发生了一些变化时,我必须反思 在ViewState中存储的GridDefinition对象中的更改。就这样,在NEXT上 回发后,可以正确地重新创建控件(例如,指示该控件的文本框) 网格列的标题文本。)
答案 5 :(得分:0)
当我研究这个问题时,它是在动态菜单的背景下,并且有一堆谷歌的回应,一起让我通过它(因为这是一个普遍的要求,我猜。)我不t有一个答案的摘要,但它可能是一个有用的起点(即google for Dynamic Menus .NET)。这个网站上也有几个问题。
答案 6 :(得分:0)
...作为另一个建议,在Page_Load太晚之后是不是绑定事件?因此他们不会在回发上被解雇。也许要检查一下......
答案 7 :(得分:0)
我再次提醒我为什么要避免使用asp - 对我而言,它似乎是一个抽象层次太多了。但是通过与javascript类比,你最终可能会遇到多个关于事件的处理程序吗?
答案 8 :(得分:0)
以下给出了完整代码的答案:
string myText = "a";
protected void Page_Load(object sender, EventArgs e)
{
WriteRows();
}
private void WriteRows()
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TextBox txt = new TextBox();
txt.Text = myText;
txt.ID = "txt1";
txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler
txt.AutoPostBack = true;
tc.Controls.Add(txt);
tr.Controls.Add(tc);
tc = new TableCell();
tc.Text = txt.Text;
tr.Controls.Add(tc);
Table1.Controls.AddAt(0,tr);
}
private void txt_TextChanged(object sender, EventArgs e)
{
myText = ((TextBox)sender).Text;
RedrawTable(); // Delete the row (incl. the TextBox) and rewrite it
}
private void RedrawTable()
{
Table1.Controls.RemoveAt(0);
WriteRows();
}
答案 9 :(得分:0)
您需要使用文本框分配ID属性。它应该可以解决你的问题。
答案 10 :(得分:0)
我有同样的问题,在我的情况下 txt.AutoPostBack = true 是我错过的。默认为假,容易忘记。