Asp.net Usercontrol LoadControl Issue
user-controls (6)
Al estar de acuerdo con Mitchel, debería poder poner una carga de página en el código de control que se activaría una vez que los controles estén completamente disponibles.
Tengo un problema al usar LoadControl( type, Params )
. Dejame explicar...
Tengo 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 el código (c #) 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 estoy agregando una instancia de usercontrol a la página usando el siguiente código:
divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails }));
Estoy usando la versión sobrecargada de LoadControl porque quiero pasar el parámetro Message al constructor. Todo esto parece funcionar bien.
Sin embargo, cuando OnPreRender()
se activa en el control de usuario ErrorDisplay, las variables lblTitle y lblDescription son ambas 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
EDITAR:
Para mayor claridad, también agregaré que el código que está agregando programáticamente usercontrol a la página se está ejecutando en respuesta a un botón presionado, por lo que la ''página de alojamiento'' ha progresado a través de Init, Page_Load y ahora está procesando los manejadores 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.
Bueno, siempre hay que agregar su propio evento de carga y llamarlo después de ejecutar el constructor y agregar el control a la página, pero no es muy diferente de lo que tiene, aunque podría elegirlo por motivos de estilo.
¡Me alegra que hayas encontrado una respuesta a tu problema!
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?
También probé el siguiente código, que produce el mismo resultado (es decir, tanto lblTitle como lblDescription son nulos)
protected void Page_Load(object sender, EventArgs e)
{
if (_ErrorMessage != null)
{
lblTitle.Text = _ErrorMessage.Message;
lblDescription.Text = _ErrorMessage.Description;
}
}
Entendí que la función LoadControl traía el control que está cargando al ''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 publicación de foros asp.net (sin respuesta) muestra el mismo problema que estoy experimentando.
Publicación en los foros de MSDN
Además, desde MSDN:
Cuando carga un control en un control de contenedor, el contenedor aumenta todos los eventos del control agregado hasta que alcanza 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 inicializar correctamente el control?
EDITAR:
Ok, entonces estoy respondiendo mi propia pregunta aquí ...
Encontré una versión respondida de la publicación del foro a la que he vinculado aquí. Aquí
Básicamente, la respuesta es que LoadControl( type, params )
no puede inferir el elemento ''page infront'' ascx para analizar y, por lo tanto, no molesta en inicializar ninguno de los controles. Cuando utiliza la LoadControl( "ascx path" )
se le da la página enfrente y por lo tanto hace todo el análisis y la revisión inicial.
Entonces, 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.
Aclamaciones
Tuve un problema similar con el evento DayRender de control del calendario, en el sentido de que quería agregar un control de usuario a 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.
Marcado ASCX
código detrás
Clase pública CPCalendarCell hereda System.Web.UI.UserControl
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
Clase final
page ASPX markup
código detrás del evento Calendar 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
Aquí hay una publicación de blog escrita por Steven Robbins. La publicación explica cómo pasar parámetros para un control de usuario usando LoadControl
, similar a lo que LoadControl(Type, object[])
, excepto que funciona :)