2008-10-27 24 views
15

Tengo un problema al usar LoadControl(type, Params). Me explico ...Asp.net Usercontrol LoadControl Issue

que tienen un control de usuario súper simple (ascx)

<%@ Control Language="C#" AutoEventWireup="True" Inherits="ErrorDisplay" Codebehind="ErrorDisplay.ascx.cs" EnableViewState="false" %> 

<asp:Label runat="server" ID="lblTitle" /> 
<asp:Label runat="server" ID="lblDescription" /> 

con código (C#) por detrás de:

public partial class ErrorDisplay : System.Web.UI.UserControl 
{ 

    private Message _ErrorMessage;  

    public ErrorDisplay() 
    { 
    } 

    public ErrorDisplay(Message ErrorMessage) 
    { 
     _ErrorMessage = ErrorMessage; 
    }  

    protected override void OnPreRender(EventArgs e) 
    { 
     base.OnPreRender(e); 

     if (_ErrorMessage != null) 
     { 
      lblTitle.Text = _ErrorMessage.Message; 
      lblDescription.Text = _ErrorMessage.Description; 
     } 
    } 
} 

En otra parte de mi aplicación web que estoy añadiendo una instancia del control de usuario a la página utilizando el siguiente código:

divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails })); 

estoy utilizando la versión sobrecargada LoadControl porque quiero pasar el parámetro Message al constructor. Todo esto aparece para que funcione bien.

Sin embargo, cuando se dispara el OnPreRender() en el control de usuario ErrorDisplay, las variables lblTitle y lblDescription son null, a pesar de tener un marcado equivalente. La variable de mensaje se ha llenado correctamente.

¿Alguien puede arrojar alguna luz sobre por qué esto puede estar pasando?

Gracias

EDIT:

Sólo por la claridad También voy a añadir que el código que se agregó mediante programación el control de usuario a la página se ejecuta en respuesta a una pulsación de botón, por lo que el 'alojamiento la página 'ha progresado a través de Init, Page_Load y ahora está procesando los controladores de eventos.

No puedo agregar los controles de usuario en una etapa anterior del ciclo de vida asp ya que se están creando en respuesta a un evento de clic de botón.

Respuesta

19

He intentado el siguiente código, así - que da el mismo resultado (es decir, tanto lblTitle y lblDescription son nulos)

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (_ErrorMessage != null) 
    { 
     lblTitle.Text = _ErrorMessage.Message; 
     lblDescription.Text = _ErrorMessage.Description; 
    } 
} 

que tenía el entendimiento de que la función LoadControl trajo el control que se está cargando hasta el 'estado' actual de la página en la que se está incluyendo. de ahí que Init, Page_Load, etc. se ejecuten como parte de la llamada LoadControl.

Curiosamente, esta (no respondida) publicación de foros asp.net presenta el mismo problema que estoy experimentando.

MSDN Forums Post

Además - Desde el MSDN:

Cuando se carga un control en un control contenedor, el contenedor plantea todos los eventos del control añadido hasta que se ha puesto al día con el evento actual. Sin embargo, el control agregado no se pone al día con el procesamiento de datos de devolución de datos.Para que un control adicional participe en el procesamiento de datos de devolución de datos, incluida la validación, el control debe agregarse en el evento Init en lugar de en el evento Load.

Por lo tanto, ¿LoadControl no debería ini- lizar correctamente el control?

EDIT:

Ok, así que estoy respondiendo a mi propia pregunta aquí ..

He encontrado una versión contestado del mensaje del foro he vinculado anteriormente Here

Esencialmente la respuesta es que el LoadControl(type, params) no puede inferir el elemento 'page fron' ascx para analizar y, por lo tanto, no molesta en inicializar ninguno de los controles. Cuando utiliza la versión LoadControl("ascx path"), se le da la página enfrente y, por lo tanto, hace todo el análisis y la revisión inicial.

Así que, en resumen, necesito cambiar el código que está iniciando el control y dividirlo en partes separadas. Es decir.

Control ErrorCntrl = LoadControl("ErrorDisplay.ascx"); 
ErrorCntrl.ID = SomeID; 
(ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail; 
divErrorContainer.Controls.Add(ErrorCntrl); 

Y debería funcionar bien ... No es tan limpio como mi intento anterior, pero al menos funcionará.

Todavía estoy abierto a sugerencias para mejorar lo anterior.

Saludos

+3

+1 y una nota de agradecimiento mía por resolver el problema que estaba teniendo. :) –

+0

Excelente seguimiento! –

-1

Según el ciclo de vida de la página asp.net, sus controles no se han agregado completamente en el procesamiento previo, ¿por qué no solo carga los valores en page_load?

+1

Esto no es correcto. [PreRender ocurre después de la carga.] (Http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events) 'provocada después de que el objeto de página haya creado todos los controles' – Chris

0

Al estar de acuerdo con Mitchel, debería poder poner una carga_pagina en el código de control que se activará una vez que los controles estén completamente disponibles.

+1

[PreRender sucede * después de * cargar] (http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events), por lo que PreRender debe estar seguro. – Chris

0

Bueno siempre hay añadiendo su propio evento de carga y decir que es después de haber corrió el constructor y añadido el control a la página, pero no es muy diferente a lo que tiene, aunque podría elegir por razones de estilo.

¡Me alegro de que hayas encontrado una respuesta a tu problema!

0

Here es una publicación de blog escrita por Steven Robbins. El mensaje explica cómo pasar parámetros para un control de usuario utilizando LoadControl, similar a lo que haría LoadControl(Type, object[]), excepto que funciona :)

0

tuve un problema similar con el evento DayRender control de calendario, en el que quería añadir un control de usuario para la colección e.Cell.Controls. Después de intentar un par de aproximaciones fallidas con el control del usuario page_load no disparando o el listbox en el archivo ascx lanzando una excepción nula, encontré que si inicialicé mi control en el formulario con LoadControl (ascx) y luego comencé a acceder a los controles de marcado en el ascx, todo funcionó bien. Este enfoque no depende del evento Page_Load en el ascx en absoluto.

ASCX marcado

código detrás

Clase CPCalendarCell Pública Hereda System.Web.UI.Control de usuario

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

End Sub 

Public Sub Add(txt As String) 
    Dim li As New ListItem(txt, txt) 
    lstDay.Items.Add(li) 
End Sub 

End Class

página ASPX marcado

código detrás evento de calendario DayRender en el formulario

Private Sub Calendar1_DayRender(sender As Object, e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender 
    Dim div As CPCalendarCell = LoadControl("~/UserControls/CPCalendarCell.ascx") 
    div.ID = "dv_" & e.Day.Date.ToShortDateString.Replace(" ", "_") 

    **e.Cell.Controls.Add(div)** 

    div.Add(e.Day.Date.Month.ToString & "/" & e.Day.Date.Day.ToString) 
    div.Add("Item 1") 
    div.Add("Item 2") 
    e.Cell.Style.Add("background-color", IIf(e.Day.IsWeekend, "whitesmoke", "white").ToString) 
End Sub