2008-09-05 17 views
7

Tengo una página bastante compleja que construye dinámicamente controles de usuario dentro de un repetidor. Este repetidor debe estar vinculado durante el evento de la página Init antes de que se inicialice ViewState o los controles de usuario creados dinámicamente no retendrán su estado.¿Qué haces cuando no puedes usar ViewState?

Esto crea un Catch-22 interesante porque el objeto al que debo vincular el repetidor necesita crearse en la carga inicial de la página y luego persistir en la memoria hasta que el usuario opte por abandonarlo o guardarlo.

Como no puedo usar ViewState para almacenar este objeto, pero lo tengo disponible durante Init, me he visto forzado a almacenarlo en Session.

Esto también tiene problemas, porque tengo que anular explícitamente el valor de la sesión durante las devoluciones para no emular cómo funciona ViewState.

Tiene que haber una mejor manera de indicar la administración en este escenario. ¿Algunas ideas?

Editar: Algunas buenas sugerencias sobre el uso de LoadViewState, pero sigo teniendo problemas con el estado no se restaura cuando lo hago.

Aquí es un poco si la estructura de la página

Página -> control de usuario -> Repetidor -> cantidad de N UserControls dynamicly creada.

Pongo el LoadViewState reemplazado en el elemento primario UserControl, ya que está diseñado para ser completamente encapsulado e independiente de la página en la que se encuentra. Me pregunto si ahí es donde está el problema.

Respuesta

1

Esto también tiene problemas, porque tengo que anular explícitamente el valor de la sesión durante las devoluciones para no emular cómo funciona ViewState.

¿Por qué tiene a nula explícitamente el valor (aparte de la gestión de memoria, etc.)? ¿No es una opción verificar Page.IsPostback y hacer algo con la variable Session o no?

1

Siempre recreé mis controles dinámicos en el evento LoadViewState. Puede almacenar la cantidad de controles necesarios para crear en viewstate y luego crear dinámicamente muchos de ellos utilizando el método LoadControl dentro del evento LoadViewState. En este caso, tiene acceso al ViewState pero todavía no se ha restaurado a los controles en la página.

0

@DancesWithBamboo:

Si me ato dinámicamente los controles allí, se ASP.NET encarga automáticamente de su estado? El problema al hacerlo en Page_Load es que viewstate ya está cargado y no agrega los controles dinámicos en el repetidor. ¿Pensaría que haría lo mismo en LoadViewState?

+0

¿Estás utilizando databinding? Nunca lo uso con asp.net y podría cambiar el campo de juego de alguna manera. Pero, LoadViewState es el evento que se debe usar para restaurar los controles dinámicos en el tiempo posterior a la devolución. PageLoad definitivamente es demasiado tarde en el ciclo de vida. – DancesWithBamboo

0

1) Probablemente haya una forma de hacer que funcione ... solo tiene que asegurarse de agregar los controles al árbol en el momento correcto. Demasiado pronto y no obtienes ViewState. Demasiado tarde y no obtienes ViewState.

2) Si no puede resolverlo, ¿tal vez puede desactivar ViewState para la página del agujero y luego confiar únicamente en la cadena de consulta para los cambios de estado? Cualquier enlace que anteriormente era una devolución de datos sería un enlace a otra URL (o una devolución de datos-redirección).

Esto realmente puede reducir el peso de la página y hacer que sea más fácil evitar problemas con ViewState.

0

@ Jonathan:

Sí, el tiempo de ejecución rellenará el estado de vista de los controles, siempre y cuando se crea el número correcto de ellos. El estado de visualización de los controles se completará después de este evento.

0

Sí, el tiempo de ejecución completará el estado de vista de los controles siempre que cree el número correcto de ellos. El estado de visualización de los controles se completará después de este evento.

¿En qué orden se llama LoadViewState? Agregué una firma de método anulada y no parece entrar en ella.

0
protected override void LoadViewState(object savedState) 
{ 
    // Put your code here before base is called 
    base.LoadViewState(savedState); 
} 

¿Eso es lo que quieres decir? ¿O quisiste decir en qué orden se procesan los controles? Creo que la respuesta es cuasialeatoria.

Además, ¿por qué no puede cargar los objetos a los que se une antes de Page_Load? Está bien llamar a su capa de negocios en cualquier momento durante el ciclo de vida de la página, si es necesario, con la excepción de pre-render y cualquier cosa posterior.

0

tengo en Null explícitamente el valor de la sesión durante no devoluciones de datos con el fin de emular cómo funciona ViewState.

Todavía tengo dudas sobre por qué no puede almacenar los objetos que está atando en la sesión. Si pudieras almacenar ese objeto en sesión, lo siguiente debería funcionar:

  1. En la primera carga, vincula tu control de usuario superior al objeto durante OnPreInit. Almacene el objeto en sesión. Viewstate se almacenará automáticamente para esos controles. Si tiene que vincular el control la primera vez en Page_Load, eso está bien, pero terminará teniendo dos eventos que llaman bind si sigue el siguiente paso.
  2. En la devolución de datos, vuelva a enlazar el control de usuario de usuario superior en el método OnPreInit con el objeto que guardó en la sesión. Todos sus controles deben volver a crearse antes de que se cargue viewstate. Luego, cuando viewstate se restaure, los valores se establecerán en lo que esté en viewstate. La única advertencia aquí es que cuando se vuelva a vincular en la devolución de datos, debe asegurarse al 100% de que se vuelva a crear la misma cantidad de controles. La clave para usar Repetidores, Cuadrículas, etc. con controles dinámicos dentro de ellos es que tienen para rebotar en cada devolución de datos antes de que se cargue viewstate. OnPreInit es generalmente el mejor lugar para hacer esto. No hay ninguna restricción técnica en el marco que dicte que debe hacer todo su trabajo en Page_Load en la primera carga.

Esto debería funcionar. Sin embargo, si no puede usar la sesión por algún motivo, tendrá que adoptar un enfoque ligeramente diferente, como almacenar lo que quiera en la base de datos después de vincular su control, extraerlo de la base de datos y volver a vincularlo de nuevo en cada devolución.

¿Me faltan algunos detalles obvios sobre su situación? Sé que puede ser muy complicado explicar las sutilezas de la situación sin publicar código.

EDITAR: He cambiado todas las referencias a OnInit a OnPreInit en esta solución.Olvidé que MS presentó este nuevo evento en ASP.NET 2.0. De acuerdo con su page lifecycle documentation, OnPreInit es donde deben crearse/recrearse los controles dinámicos.

0

Al crear controles dinámicos ... solo los rellene en la carga inicial. Afterwords recreé los controles en la devolución de datos en el evento de carga de página, y viewstate parece manejar la repoblación de los valores sin problemas.

4

El método LoadViewState en la página es definitivamente la respuesta. Aquí está la idea general:

protected override void LoadViewState(object savedState) { 
    var savedStateArray = (object[])savedState; 

    // Get repeaterData from view state before the normal view state restoration occurs. 
    repeaterData = savedStateArray[ 0 ]; 

    // Bind your repeater control to repeaterData here. 

    // Instruct ASP.NET to perform the normal restoration of view state. 
    // This will restore state to your dynamically created controls. 
    base.LoadViewState(savedStateArray[ 1 ]); 
} 

SaveViewState necesita para crear la matriz savedState que estamos utilizando anterior:

protected override object SaveViewState() { 
    var stateToSave = new List<object> { repeaterData, base.SaveViewState() }; 
    return stateToSave.ToArray(); 
} 

No se olvide de unirse también el repetidor en Init o carga utilizando código como este:

if(!IsPostBack) { 
    // Bind your repeater here. 
} 
Cuestiones relacionadas