【问题标题】:Is a control's OnInit called even when attaching it during parent's OnPreRender?即使在父级的 OnPreRender 期间附加控件时也会调用控件的 OnInit 吗?
【发布时间】:2011-01-26 14:15:39
【问题描述】:

我最初的理解是asp.net页面生命周期在正常情况下对所有页面和控件运行一次。当我在容器的 OnPreRender 期间附加控件时,遇到了未调用控件的 OnInit 的情况。好的,我认为这是我的代码中的一个错误,并通过较早地附加控件进行了修复。

但是就在今天,我遇到了一种情况,在为其他所有人完成正常的 OnInit 之后,似乎调用了控件的 OnInit。请参阅下面的堆栈。似乎在页面的 PreRender 期间,控件的 OnInit 被调用,因为它正在被动态添加。

所以我只想确认一下 ASP.NET 的行为是什么?它是否真的跟踪每个控件生命周期的阶段,并且在添加新控件时,它会从一开始就运行?

[HttpException (0x80004005): 在 DataBind、Init、Load、PreRender 或 Unload 阶段无法修改控件集合。] System.Web.UI.ControlCollection.Add(控制子)+8678663 MyCompany.Web.Controls.SetStartPageWrapper.Initialize() MyCompany.Web.Controls.SetStartPageWrapper.OnInit(EventArgs e) System.Web.UI.Control.InitRecursive(控件命名容器)+333 System.Web.UI.Control.InitRecursive(控件命名容器)+210 System.Web.UI.Control.AddedControl(Control control, Int32 index) +198 System.Web.UI.ControlCollection.Add(控制子)+80 MyCompany.Web.Controls.PageHeader.OnPreRender(EventArgs e) 在 System.Web.UI.Control.PreRenderRecursiveInternal() +80 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842

【问题讨论】:

    标签: asp.net


    【解决方案1】:

    控件的 OnInit 在添加到控件树后立即被调用。在您的堆栈中,您可以看到这种情况发生了:

    System.Web.UI.Control.AddedControl(Control control, Int32 index) +198   
    System.Web.UI.ControlCollection.Add(Control child) +80 
    

    那么这就触发了:

    MyCompany.Web.Controls.SetStartPageWrapper.OnInit(EventArgs e) 
    

    因此,无论在生命周期的哪个阶段添加它,它都会启动 OnInit。

    Egghead has a good image depicting normal event lifecycles between pages and controls,但请记住,如果某些事件尚不存在,则无法执行事件……如果只是添加,则必须在该点而不是何时赶上事件如果控件在标记或CreateChildControls 中,就会发生这种情况。

    【讨论】:

    • 不仅如此,其他控件事件(如 Load)也可能触发,因此控件可以“赶上”控件树的其余部分在生命周期中的位置。
    • @William - 好点,在你写评论的时候找到一张图片来说明这一点:)
    • 正确,每个控件在附加后立即“追赶”到新父级在生命周期中的当前状态。每个控件都有一个私有变量 _controlState 来跟踪: 反射器中的代码:protected internal virtual void addedControl(Control control, int index) ... if (this._controlState >= ControlState.ChildrenInitialized) { control.InitRecursive(namingContainer); ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 2016-06-02
    • 2011-07-22
    • 2010-12-14
    相关资源
    最近更新 更多