这是一个常见问题,它与页面生命周期有关:
看看以下问题:
按钮数组上的单击事件
点击事件后按钮数组消失
动态创建一个 ImageButton
现在创建动态控件时要记住的基本步骤是:
- 当您不使用母版页时,应在
PreInit
事件中创建动态控件,如果是,则在Init
事件中创建控件
- 避免在这些事件中设置可以在每个帖子中更改的属性,因为当应用视图状态时(在帖子事件中),这些属性将被覆盖
- 每次发布页面时都必须创建动态控件,避免这种情况
if(!this.IsPostBack) this.CreatemyDynamicControls();
- 当您在
PreInit
orInit
事件中创建控件时,它们的状态将在发布事件中自动设置,这意味着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
否则它们将不会被引发。
...我知道我讨厌这种行为,这就是我喜欢 MVC 的原因
作为在设计时创建的控件的快速参考:注意LoadViewState
方法是如何在and事件之后但在事件之前调用的。该事件被认为是稳定的,因为在此事件中您可以访问控件的视图状态。另请注意,该方法表示导致回发的控制事件,可以是,,,等,此事件在事件之后处理PreInit
Init
Load
Load
RaisePostBackEvent
SelectedIndexChanged
Click
Load
有关完整的详细规范,请阅读MSDN 页面生命周期文档