这是一个常见问题,与页面生命周期有关:
看一下以下问题:
单击数组按钮事件
单击事件后按钮数组消失
动态创建ImageButton
现在,在创建动态控件时需要记住的基本步骤是:
- 如果您没有使用主页,动态控件应该在
PreInit
事件中创建;如果您使用了主页,则应该在Init
事件中创建控件。
- 在这些事件中避免设置可以在每个提交中更改的属性,因为当视图状态被应用(在提交事件中)时,属性将被覆盖。
- 必须每次页面提交时都创建动态控件,请避免使用
if(!this.IsPostBack) this.CreatemyDynamicControls();
- 当您在
PreInit
或Init
事件中创建控件时,它们的状态将自动在提交事件中设置,这意味着在LoadComplete
事件中,即使您在每个提交中重新创建它们,甚至在您没有显式设置它们的状态时,您的控件也将包含它们的状态。请注意,在处理设计时创建的控件时,此行为是不同的,此时状态设置的事件是Load事件
- 事件订阅应该在
PageLoadComplete
之前进行,否则它们将不会被触发。
请参考以下来自MSDN的描述
如果控件在运行时动态创建或在数据绑定控件的模板中声明,它们的事件最初与页面上其他控件的事件不同步。例如,在运行时添加的控件的 Init 和 Load 事件可能比相同事件的声明性创建控件的事件晚得多。因此,从它们被实例化的时刻起,动态添加的控件和模板中的控件依次引发它们的事件,直到它们赶上将其添加到 Controls 集合期间的事件。
以上内容对我来说不是很清晰,但我找到了以下内容。下面的
TextBox
是在设计时创建的。
protected void Page_PreInit(object sender, EventArgs e)
{
this.txtDesignTextBox1.Text = "From PreInit";
this.txtDesignTextBox1.Text += DateTime.Now.ToString();
}
protected void Page_Init(object sender, EventArgs e)
{
this.txtDesignTextBox2.Text = "From Init";
this.txtDesignTextBox2.Text += DateTime.Now.ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
this.txtDesignTextBox3.Text = "From Load";
this.txtDesignTextBox3.Text += DateTime.Now.ToString();
}
起初你可能认为每篇文章中的所有文本框都会更新为当前日期,但这并不是事实,因为它们在设计时创建,严格遵循ASP.Net页面生命周期,这意味着,在PreInit和Init事件之后,它们的状态被覆盖,只有txtDesignTextBox3在每篇文章中更新,因为它的Text属性在视图状态被设置之后(在Load事件中)更新。
但对于动态控件,行为是不同的,请记住MSDN的描述:
对于在运行时添加的控件,Init和Load事件可能会在页面生命周期中发生得更晚。
请考虑以下内容:
protected void Page_PreInit(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Init(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Load(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
在这种情况下,控件的行为稍有不同,在每个帖子中,
控件甚至包括在Load
事件中创建的控件都不会被更新。
原因是它们的生命周期事件在页面生命周期后期发生,这意味着它们的状态被覆盖,即使是在
Load
事件之后也是如此。
要解决这个问题,您可以使用
LoadComplete
事件,在该事件中可以更改动态控件的状态:
protected void Page_LoadComplete(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
在这种情况下,状态将在每个帖子中更新。
但是,请注意,在
LoadComplete
事件之前订阅动态控件事件,否则它们将不会被引发。
作为设计时创建的控件的快速参考:请注意,
LoadViewState
方法在
PreInit
和
Init
事件之后但在
Load
事件之前被调用。
Load
事件被认为是
稳定的,因为在此事件中,您可以访问您的控件的视图状态。还要注意,
RaisePostBackEvent
方法表示导致回发的控件事件,这可以是
SelectedIndexChanged
、
Click
等,此事件在
Load
事件之后处理。
![enter image description here](https://istack.dev59.com/eDLuE.webp)
如需完整详细规范,请阅读MSDN页面生命周期文档
Postback
后检查了控件的存在吗?当页面生命周期结束
时,所有控件都将被Disposed
。每次Postback
都需要重新创建Dynamic Control
。上述代码应该在页面的Initialization
事件中。 - Pankaj