asp.net - 为什么子控件在它们的容器之前初始化?

标签 asp.net webforms page-lifecycle

尽管使用 WebForms 多年,我仍然发现自己时不时地对事件生命周期感到困惑。这与其说是一个需要解决的问题,不如说是希望更好地理解为什么事情会按照它们的方式工作。

假设你有一个表格:

默认.aspx:

<form>
  <MyControls:UserControl1 runat="server">
</form>

用户控件 1:ascx:
<MyControls:UserControl2 runat="server">
OnInit事件按以下顺序发生:
UserControl2_OnInit
UserControl1_OnInit
Default_OnInit

这不只是低音回声吗? Init 代码不应该按照控件的创建顺序运行吗?父控件不应该在 OnInit 运行之前初始化子控件的属性吗?也就是说,虽然您可以在标记中初始化子控件的属性,但没有直接的方法让父控件能够动态设置子控件的属性,这些属性可用于其 OnInit 事件。

我最终做的是这样的事情:
override void UserControl2_OnInit()
{
    NamingContainer.OnInit += new EvenHandler(UserControl1_ActualInit);
}
protected void UserControl2_ActualInit(..) {
  // do actual init code here, which will occur before OnLoad but after it's parent
  // OnInit
}

所以这不是一个不可逾越的问题。我只是不明白为什么它首先是一个问题。

我意识到也许您可能希望能够在 OnInit 代码中初始化所有子控件。很好,您应该能够首先调用 base.OnInit,而不是之后调用您自己的初始化代码,这应该会导致所有子控件 OnInit 事件运行。但是事件生命周期不是那样工作的。 Init 事件不是递归链接的,它们似乎独立于父事件运行,并且最里面的事件总是首先运行。但是,如果将它们简单地递归链接起来,那么生活似乎会容易得多,这样您就可以在任何给定情况下在做事之前调用(或不调用)基本事件。是否有什么我遗漏的东西使这种看似违反直觉的情况变得可取甚至是必要的?

最佳答案

This document应该是您生命周期问题的主要真相来源。

基本上, OnInit 触发 控件的内部初始化完成后 .由于页面控件是第一个初始化的控件,并且在它的内部初始化期间它会初始化所有子控件(可能按照 Designer.cs 文件给出的顺序),因此页面的 OnInit 事件是最后一个调用的有意义的,因为直到它的所有子控件都被初始化并且它们的 OnInit 事件被触发时它才完成初始化。从图形上看,它看起来像这样:

Page internal init
    Sub-control1 internal init
        Sub-sub-control3 internal init
        Sub-sub-control3 init finished / OnInit fired
    Sub-control1 init finished / OnInit fired
    Sub-control2 internal init
    Sub-control2 init finished / OnInit fired
Page init finished / OnInit fired

所以在这种情况下初始化的顺序是:
  • 子子控件3 OnInit
  • 子控件1 OnInit
  • 子控件2 OnInit
  • 页面 OnInit

  • 负载也类似。通常,您应该将大多数事件视为控件将首先通过其内部过程(包括在所有子控件上调用相同的事件),然后再触发您的自定义事件处理代码。

    您发现的大多数示例都专门使用 Page_Load,因为这应该是该阶段中调用的最后一个事件(并且是在加载回发数据之后)。首先调用 Page_Load 并冒着使您的自定义事件处理代码的控件未处于完全加载状态的风险不会很好地工作。

    关于asp.net - 为什么子控件在它们的容器之前初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4945777/

    相关文章:

    ASP.NET:Response.Redirect(...) 之后代码会发生什么?

    c# - 什么是数据表示控件的 ItemCommand 和 ItemDatabound?

    javascript - 如何根据用户对用户控件的操作启用表单控件,而不需要回发

    asp.net - 仅 Visual Studio 本地化和表单 : asp:button, asp :CheckBox reading default language . resx 文件

    c# - SetFocus 只能在 PreRender 之前和期间调用

    c# - 页面退出时执行操作

    c# - 如何修改存储过程或 ASP.net 代码以在插入新行后获取自动生成的 Id

    asp.net - 子页面不从主页面获取样式

    css - Bootstrap Glyphicon 与文本框对齐

    c# - 将 QueryString 值分配为隐藏字段值