如何将事件处理程序附加到在运行时创建的ASP.NET控件?

大家早上好。

我有一个与控件和事件处理相关的问题。 让我们说我想创建一个LinkButton

 protected void loadLinkButton() { ContentPlaceHolder content = (ContentPlaceHolder)this.Master.FindControl("MainContent"); LinkButton lnk = new LinkButton(); lnk.ID = "lnikBtn"; lnk.Text = "LinkButton"; lnk.Click += new System.EventHandler(lnk_Click); content.Controls.Add(lnk); } 

这是事件处理程序:

 protected void lnk_Click(object sender, EventArgs e) { Label1.Text = "ok!"; } 

如果我在Page_Load运行loadLinkButton函数一切正常。 但是当我尝试通过单击简单按钮运行loadLinkButton ,会创建链接按钮但不处理事件。

 protected void Button1_Click(object sender, EventArgs e) { loadLinkButton(); } 

我有什么方法可以解决它吗? 或者必须始终在Page_LoadPage_init等上重新生成Page_init

使用动态控件时,我总是在Page_Init中添加控件,因为viewstate加载将在Init之后立即发生。 如果将其添加到Page_Load,则可能会丢失viewstate。 只需确保您提供唯一的控件ID。

了解ASP.Net如何确定要调用的事件非常重要。 使用隐藏字段传递每个事件的来源:

  

每当页面加载时,它从该字段中提取事件源,然后确定要调用的事件。 现在这一切都适用于通过标记添加的控件,因为整个控制树在每个请求时都会重新生成。

但是,您的控件只添加了一次。 发生回发时,您的控件不再作为树中的服务器控件存在,因此事件永远不会触发。

避免这种情况的简单方法是确保每次加载页面时都会添加动态控件 ,无论是通过Page_Init事件还是Page_Load事件。

你是对的。 这是预期的行为。 Page_Load和Page_Init将是您应该添加它的事件。

这是因为当您单击动态生成的链接按钮时,您会回发到服务器。 在那里你做了一个全新的页面加载,但你原来的buttonclick(生成链接)现在从未发生过,因此链接按钮永远不会发生,并且不能抛出事件。

另一种方法是使用Visible = false将动态添加的链接按钮静态添加到页面中。 当您单击其他按钮时,使其可见。

我不确定你遇到了什么问题,但你应该按照@johnofcross的建议把动态控件代码放在Page_Init中:

 public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void Page_Init(object sender, EventArgs e) { CreateControls(); } private void CreateControls() { var lb = new LinkButton(); lb.Text = "Click Me"; lb.Click += lb_Click; ph.Controls.Add(lb); ph.DataBind(); } void lb_Click(object sender, EventArgs e) { lblMessage.Text = "Button is clicked!"; } }