动态控件:如果在Page_Load期间重新创建,则不会触发相关事件

时间:2012-08-01 03:30:55

标签: asp.net

免责声明:我已阅读the ASP.net page life cycle,并且我还阅读了与动态控件相关的several good articles,但我必须遗漏一些内容。

背景:我目前正在开发一个网站,需要根据用户的输入创建大量动态内容。我理解,为了使动态控件保持不变并使其事件正确连接,我需要在每个页面上重新创建这些动态控件。

由于我的项目的性质,我的代码不知道要创建什么控件,除非它有一些关于用户选择的信息。我将用户的选择存储在ViewState中,Page_Init中不可用,因为它尚未加载。因此,我必须等到Page_PreLoadPage_Load才能阅读ViewState,然后重新创建动态控件。

我不理解的部分:当我尝试在Page_Load期间重新创建控件时,控件仍然存在,但相关事件似乎没有触发。例如,单击我创建的LinkButton不会触发我连接到其Click事件的方法,即使按钮本身仍然存在。

我偶然发现的一个奇怪的解决方案是,我可以在Page_PreLoad期间重新创建控件,然后事件正确触发。

我的问题(或问题,而不是):为什么我的问题似乎在Page_PreLoad而不是Page_Load期间重新创建控件时消失了?这是安全的做法吗?我从未见过使用Page_PreLoad的任何其他代码,这让我很谨慎。这个解决方案对我有用,但是我有什么陷阱可能会丢失吗?我是否在不知不觉中为自己以后的失败做好准备?

我的代码,其中LoadDocument()是一种创建控件并将其填充到静态Panel控件中的方法:

protected void Page_PreLoad(object sender, EventArgs e)
{
    if (ViewState["xmlfilename"] != null)
    {
        LoadDocument(ViewState["xmlfilename"].ToString());
    }
}

2 个答案:

答案 0 :(得分:1)

您的活动将在ProcessPostData期间处理。哪个控件触发回发也是发布数据。如果您的控件当时不存在,则不会收到该事件。

我同意Init太早,Load太晚了。

您需要做的是在加载视图状态后立即创建这些控件。

页面生命周期中没有此事件。但是,所有函数都是虚函数,您可以覆盖之间调用的函数。

加载依赖于ViewState中存储的值的控件的最佳位置是LoadViewState函数。

  • 覆盖此功能。
  • 请记住在一开始就调用base.LoadViewState。
  • 根据ViewState值创建控件。

现在所有控件事件都应该正常启动。

答案 1 :(得分:1)

可能你读过我对这个主题的一个答案:

我可以告诉你,我使用PreLoad事件生成代码并且工作正常

但对于新开发,我使用Init事件,为什么?因为它是微软的推荐,因此它可以被视为一种标准,并且技术优势如ViewState的自动加载,主题支持和最重要的(从我的观点来看),动态控件事件是同步的静态控件。

您的问题是正确的,在Init事件中尚未加载ViewState,但这并不会阻止您访问Form集合

我创建了一个用于学习目的的页面,我在按需创建动态控件,我在Init事件中执行此操作。我正在创建TextBoxes,并且在每个帖子中,当文本发生更改时,他们会提升TextChanged事件。

注意:在继续之前,我想提醒您ViewState已加载匹配控件的ID ,这就是为什么使用相同的ID重新创建动态控件的好习惯

这是代码:

ASPX

<asp:HiddenField runat="server" ID="numberOfDynamicControls" Value="0" />
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Button Text="Add Control" runat="server" ID="addControl" OnClick="addControl_Click" />
<asp:Label ID="lblMessage" runat="server" />

ASPX代码背后

    protected void Page_Init(object sender, EventArgs e)
    {
        this.CreateDynamicControls();
    }

    protected void addControl_Click(object sender, EventArgs e)
    {
        var n = int.Parse(this.numberOfDynamicControls.Value);
        n++;
        this.numberOfDynamicControls.Value = n.ToString();
        this.myPanel.Controls.Add(this.CreateTextbox(n));
    }

    private void CreateDynamicControls()
    {
        int n = 0;

        if (!string.IsNullOrWhiteSpace(this.Request.Form["numberOfDynamicControls"]))
        {
            n = int.Parse(this.Request.Form["numberOfDynamicControls"]);
        }

        for (int i = 0; i < n; i++)
        {
            var t = this.CreateTextbox(i + 1);
            t.TextChanged += (x, y) => this.lblMessage.Text += "<br/>" + (x as TextBox).ID + " " + (x as TextBox).Text;

            this.myPanel.Controls.Add(t);
        }
    }

    private TextBox CreateTextbox(int index)
    {
        var t = new TextBox { ID = "myTextbox" + index.ToString(), Text = "de" };

        return t;
    }