事件处理程序未针对动态创建的控件触发

时间:2008-11-21 03:26:05

标签: .net asp.net events

我在动态创建的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();
  }
}

是否有人有解决方案以便始终触发事件?

11 个答案:

答案 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 是我错过的。默认为假,容易忘记。