1

免责声明:我已经阅读了 ASP.net 页面生命周期,并且我还阅读了几篇有关动态控件的 文章,但我一定遗漏了一些东西。

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

由于我的项目的性质,我的代码不知道要创建什么控件,除非它包含有关用户选择的内容的一些信息。我将用户的选择存储在 中,因为它尚未加载,所以它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());
    }
}
4

2 回答 2

1

Probably you read one of my answers on this topic:

I can tell you that I have code on production using the PreLoad event and it has worked fine

But for new development I am using the Init event, Why? Because it is the Microsoft recommendation and therefore it can be considered as an standard, and the technical benefits such the automatic load of the ViewState, theme support, and the most important (from my point of view), the dynamic controls events are sync with the static controls.

Your concern is right, in the Init event the ViewState has not been loaded yet, but that doesn't stop you to access the Form collection

I created a page for learning purpose where I'm creating dynamic controls on demand, and I'm doing it in the Init event. I'm creating TextBoxes and on each post they raise their TextChanged event when the text is changed.

NOTE: before continue I would like to remind you that the ViewState is loaded matching the control's ID's, that's why it's a good practice to re-create always the dynamic controls using the same ID

This is the code:

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 code behind

    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;
    }
于 2012-08-01T04:41:37.797 回答
1

您的事件在ProcessPostData. 哪个控件触发了回发,也是发布数据。如果你的控件当时不存在,它就不会接收到该事件。

我同意Init这为时过早,也Load为时已晚。

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

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

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

  • 覆盖这个函数。
  • 记得在一开始就调用 base.LoadViewState。
  • 根据 ViewState 值创建控件。

现在您的所有控件事件都应该正确触发。

于 2012-08-01T04:20:57.177 回答