开发者

Find out what stage of the life cycle a control is up to in ASP.NET WebForms

开发者 https://www.devze.com 2023-01-23 05:35 出处:网络
From the outside of a control, is it possible to find out what stage of the Page LifeCycle (Init, Load, PreRender etc), a particular co开发者_开发技巧ntrol or page is up to?

From the outside of a control, is it possible to find out what stage of the Page LifeCycle (Init, Load, PreRender etc), a particular co开发者_开发技巧ntrol or page is up to?

For example, in pseudo code:

if myControl.CurrentLifeCycle == Lifecycle.Init
{ do something }


I'm afraid there is no builtin function to check in what Page-Lifecycle phase a Page is. It is also difficult to add this functionality without handling all events in the Page itself, because some events are protected. Therefore you could also inherit the LifeCycleListener-class from Control, add it in the constructor to the page listening and override all events.

If you only need the public "phases" PreInit,Init,Load,DataBinding,PreRender,Unload,Disposed have a look at following approach(VB.Net, but i think you'll get the idea):

Public Enum LifeCyclePhase
    AfterPreInit
    AfterInit
    AfterLoad
    AfterDataBinding
    AfterPreRender
    AfterUnload
    AfterDisposed
End Enum

Public Interface ITrackingLifeCycle
    ReadOnly Property GetLifeCycleListener() As LifeCycleListener
End Interface

Public Class LifeCycleListener

    Public Sub New(ByVal ctrl As Control)
        Me._PageListening = ctrl.Page
        AddListener()
    End Sub

    Private _CurrentPhase As LifeCyclePhase
    Private _PageListening As Page

    Public ReadOnly Property CurrentPhase() As LifeCyclePhase
        Get
            Return _CurrentPhase
        End Get
    End Property

    Public ReadOnly Property PageListening() As Page
        Get
            Return _PageListening
        End Get
    End Property

    Private Sub AddListener()
        AddHandler _PageListening.PreInit, AddressOf PreInit
        AddHandler _PageListening.Init, AddressOf Init
        AddHandler _PageListening.Load, AddressOf Load
        AddHandler _PageListening.DataBinding, AddressOf DataBinding
        AddHandler _PageListening.PreRender, AddressOf PreRender
        AddHandler _PageListening.Unload, AddressOf Unload
        AddHandler _PageListening.Disposed, AddressOf Disposed
    End Sub

    Private Sub PreInit(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterPreInit
    End Sub

    Private Sub Init(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterInit
    End Sub

    Private Sub Load(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterLoad
    End Sub

    Private Sub DataBinding(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterDataBinding
    End Sub

    Private Sub PreRender(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterPreRender
    End Sub

    Private Sub Unload(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterUnload
    End Sub

    Private Sub Disposed(ByVal sender As Object, ByVal e As EventArgs)
        Me._CurrentPhase = LifeCyclePhase.AfterDisposed
    End Sub
End Class

The handler in this class are called after the handler in the page itself, so if you f.e. check the CurrentPhase in Page.Init you'll get PreInit. Therefor i have called this phase AfterPreInit.

Partial Public Class _Default
    Inherits System.Web.UI.Page
    Implements ITrackingLifeCycle

    Private lcl As New LifeCycleListener(Me)

    Public ReadOnly Property GetLifeCycleListener() As LifeCycleListener Implements ITrackingLifeCycle.GetLifeCycleListener
        Get
            Return lcl
        End Get
    End Property

You can now check the lifecycle-phase everywhere, even without a reference to a control via HttpContext.Current:

Public Class FooClass
    Public Shared Sub Foo()
        If Not (HttpContext.Current Is Nothing OrElse HttpContext.Current.Handler Is Nothing) Then
            If TypeOf HttpContext.Current.CurrentHandler Is ITrackingLifeCycle Then
                Dim page As ITrackingLifeCycle = DirectCast(HttpContext.Current.CurrentHandler, ITrackingLifeCycle)
                Dim phase As LifeCyclePhase = page.GetLifeCycleListener.CurrentPhase
            End If
        End If
    End Sub
End Class

This is neither tested sufficiently nor used by myself and certainly improvable, but maybe it helps you in your current situation.


I think what you try to achieve is conceptually wrong because you are thinking at the page events as page state. The page can’t be at “OnInit/OnLoad/…” state just because it’s an event.

What do you need it for? maybe we could suggest you a better approach to achieve your goal.


The „outside of your control” is the „inside” of another control or page or something being in a linked state of the lifecycle. You know its state already without testing.


I found out there is actually an internal property of the Page class that does just what I am looking for: it is an enum called ControlState:

internal enum ControlState
{
Constructed,
FrameworkInitialized,
ChildrenInitialized,
Initialized,
ViewStateLoaded,
Loaded,
PreRendered
}

I believe it is possible to access internal members in C#4, see here


As far as I understand the page lifecycle, you can't do it. Basically, Page class is the guy that has to raise events in a specific order. There is nothing in built that will tell the stage of processing. But in order to something, you can create a property and set up this property in different stages of processing.

0

精彩评论

暂无评论...
验证码 换一张
取 消