simple page net example code aspx asp asp.net webforms page-lifecycle

asp.net - page - ¿Por qué los subcontroles se inicializan antes de sus contenedores?



events asp net (2)

Este documento debería ser la fuente principal de la verdad para sus preguntas sobre el ciclo de vida.

Básicamente, OnInit se activa después de que la inicialización interna de un control finaliza . Como el control de página es el primer control inicializado, y durante su inicialización inicial, inicializa todos los subcontroles (tal vez en el orden que le da el archivo Designer.cs), entonces tiene sentido que el evento OnInit de la página sea el último llamado , ya que no se ha terminado de inicializar hasta que se hayan inicializado todos sus subcontroles y se hayan activado sus eventos OnInit. Gráficamente, se ve así:

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

Entonces el orden de los inits en este caso es:

  1. Sub-sub-control3 OnInit
  2. Subcontrol1 OnInit
  3. Subcontrol2 OnInit
  4. Página OnInit

Cargar también funciona de manera similar. En general, debe tratar la mayoría de los eventos como si el control pasara por su proceso interno primero (lo que incluye llamar al mismo evento en todos los subcontroles) y luego desencadenar su código personalizado de manejo de eventos.

La mayoría de los ejemplos que encuentras usan Page_Load específicamente porque ese debería ser el último evento llamado en esa fase (y es después de que se carguen los datos posteriores). No funcionaría muy bien que se llame primero a Page_Load y se corre el riesgo de tener controles que no estén completamente cargados para su código de manejo de eventos personalizado.

A pesar de trabajar con WebForms durante años, todavía me encuentro confundido sobre el ciclo de vida del evento de vez en cuando. No se trata tanto de un problema que deba resolverse, sino de una mejor comprensión de por qué las cosas funcionan de la manera en que lo hacen.

Supongamos que tiene un formulario:

Default.aspx:

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

UserControl1: ascx:

<MyControls:UserControl2 runat="server">

Los eventos OnInit ocurren en este orden:

UserControl2_OnInit UserControl1_OnInit Default_OnInit

¿No es esto solo un bajo-ackwards? ¿No debería ejecutarse el código Init en el orden en que se crean los controles? ¿No debería un control principal poder inicializar las propiedades de un niño antes de que se ejecute OnInit? Es decir, aunque puede inicializar las propiedades de los subcontroles en el marcado, no hay una forma directa de que un control principal pueda establecer dinámicamente las propiedades del control secundario que estará disponible para su evento OnInit.

Lo que terminé haciendo es algo como esto:

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 }

Entonces no es un problema insuperable. Simplemente no entiendo por qué es un problema en primer lugar.

Me doy cuenta de que quizás desee poder tener todos sus controles secundarios inicializados en su código OnInit. Tan bien, debería poder llamar a base.OnInit primero, en lugar de después, a su propio código de inicialización, que debería hacer que se ejecuten todos los eventos OnInit de control infantil. Pero el ciclo de vida del evento no funciona de esa manera. Los eventos Init no están encadenados recursivamente, parecen funcionar de forma independiente los eventos principales, y el más interno siempre se ejecuta primero. Pero parece que la vida sería mucho más fácil si simplemente estuvieran encadenados de manera recursiva, por lo que podría llamar al evento base (o no) antes de que haga lo suyo en cualquier situación dada. ¿Hay algo que me falta que hace que esta situación aparentemente contra intuitiva sea deseable o incluso necesaria?


La mentalidad para los controles padre e hijo de asp.net es:

Los padres saben todo sobre sus hijos, pero los niños no saben nada sobre sus padres.

Esta mentalidad tiene sentido para los controles de servidor reutilizables. La reutilización necesita el control infantil personalizado sin suposiciones sobre la página en la que se utiliza.

El fragmento que me da me hace adivinar que los controles de usuario de su hijo no están destinados a ser reutilizables como tales; sino que son controles especializados que usas para analizar las complejidades de una interfaz de usuario grande y complicada.

En este caso, aún trataría de trabajar con la mentalidad de "los niños no saben nada sobre sus padres". Piensa http://www.google.co.uk/search?q=gof+mediator+pattern donde la página principal es el mediador entre tus hijos (la página wikipedia es buena).

Pero sus hijos aún necesitan saber algo sobre el derecho de los padres, porque están haciendo interacciones de UI complejas. Puede abordar esto con interfaces. Cada niño depende no del padre, sino de una interfaz que define exactamente a qué necesitan acceder los niños. Como dice http://en.wikipedia.org/wiki/SOLID , "depende de las abstracciones, no de las concreciones". HACER una interfaz por control secundario: ''muchas interfaces específicas del cliente son mejores que una interfaz de propósito general''

Pero todo termina buscando una ingeniería excesiva, ¿no? Resulta que una IU con componentes en la que los componentes deben interactuar, simplemente es compleja y los componentes pueden resultar muy complicados. Este fue, en mi opinión, una de las razones por las cuales los formularios web de MS ajax controlan perder jQuery & c. incluso antes de que llegara MVC.

Agregue a esto que los formularios web ui son muy difíciles de probar por unidad; y su confianza en las inmersiones de calidad de su software.

Recomiendo: si puedes, escapa a una reescritura en MVC. Si no puede, considere abandonar los controles del lado del servidor que hacen el comportamiento del lado del cliente, y use jQuery en su lugar. Si no puedes hacer eso, simplifica simplifica la interfaz de usuario. Incluso si eso lo hace menos funcional. Si no quiere eso, entonces sus elecciones son: pagar los gastos de ingeniería de la IU; o pagar el gasto de no diseñarlo bien.