Domanda

Sto riscontrando un problema durante l'utilizzo di LoadControl (type, Params) . Lasciami spiegare ...

Ho un controllo utente super semplice (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 codice (c #) dietro a:

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;
        }
    }
}

Altrove nella mia applicazione Web sto aggiungendo un'istanza del controllo utente alla pagina utilizzando il seguente codice:

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

Sto usando la versione sovraccarica di LoadControl perché voglio passare il parametro Message al costruttore. Tutto questo appare per funzionare bene.

Tuttavia, quando OnPreRender () viene attivato con il controllo utente ErrorDisplay, le variabili lblTitle e lblDescription sono entrambe null , nonostante abbiano un equivalente di markup. La variabile del messaggio è stata popolata correttamente.

Qualcuno può far luce sul perché ciò potrebbe accadere?

Grazie

Modifica

Per chiarezza, aggiungerò anche che il codice che sta aggiungendo programmaticamente il controllo utente alla pagina è in esecuzione in risposta alla pressione di un pulsante, quindi la "pagina di hosting" è passata attraverso Init, Page_Load e ora sta elaborando l'evento gestori.

Non riesco ad aggiungere i controlli utente in una fase precedente del ciclo di vita dell'ASP mentre vengono creati in risposta a un evento di clic sul pulsante.

È stato utile?

Soluzione

Ho provato anche il seguente codice - che produce lo stesso risultato (cioè sia lblTitle che lblDescription sono nulli)

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

Ho capito che la funzione LoadControl ha portato il controllo che sta caricando allo "stato" corrente della pagina in cui viene inclusa. quindi Init, Page_Load ecc vengono eseguiti come parte della chiamata LoadControl.

È interessante notare che questo post sui forum asp.net (senza risposta) presenta lo stesso problema che sto vivendo.

Post nei forum MSDN

Inoltre - Da MSDN:

  

Quando si carica un controllo in un controllo contenitore, il contenitore genera tutti gli eventi del controllo aggiunto fino a quando non ha raggiunto l'evento corrente. Tuttavia, il controllo aggiunto non raggiunge l'elaborazione dei dati postback. Affinché un controllo aggiuntivo possa partecipare all'elaborazione dei dati di postback, inclusa la convalida, è necessario aggiungere il controllo nell'evento Init anziché nell'evento Load.

Pertanto LoadControl non dovrebbe inizializzare correttamente il controllo?

Modifica

Ok, quindi sto rispondendo alla mia domanda qui ..

Ho trovato una versione con risposta del post sul forum a cui ho collegato sopra Qui

Sostanzialmente la risposta è che LoadControl (type, params) non può dedurre l'ascx 'page infront' da analizzare e quindi non si preoccupa di inizializzare nessuno dei controlli. Quando si utilizza la versione LoadControl (" ascx path ") , viene fornita la pagina infront e quindi tutte le analisi e l'inizializzazione.

Quindi, in sintesi, devo cambiare il codice che sta inizializzando il controllo e dividerlo in parti separate. Cioè.

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

E dovrebbe funzionare bene .. Non è pulito come il mio precedente tentativo, ma almeno funzionerà.

Sono ancora aperto a suggerimenti per migliorare quanto sopra.

Saluti

Altri suggerimenti

D'accordo con Mitchel, dovresti essere in grado di inserire un page_load nel codice di controllo stesso che verrebbe attivato dopo che i controlli saranno completamente disponibili.

Bene, c'è sempre l'aggiunta del proprio evento di caricamento e la sua chiamata dopo aver eseguito il costruttore e aggiunto il controllo alla pagina, ma non è molto diverso da quello che hai, anche se potrei sceglierlo per motivi di stile.

Sono contento di aver trovato una risposta al tuo problema!

Qui è un post sul blog scritto da Steven Robbins. Il post spiega come passare i parametri per un controllo utente usando LoadControl , simile a quello che farebbe LoadControl (Type, object []) , tranne che funziona :)

Ho avuto un problema simile con l'evento DayRender del controllo Calendar, in quanto volevo aggiungere un controllo utente alla raccolta e.Cell.Controls. Dopo aver provato un paio di approcci non riusciti con il page_load del controllo utente non attivato o la casella di riepilogo sull'ascx che ha generato un'eccezione nulla, ho scoperto che se avessi inizializzato il mio controllo sul modulo con LoadControl (ascx) e poi avessi iniziato ad accedere ai controlli di markup sul ascx, tutto ha funzionato bene. Questo approccio non dipende affatto dall'evento Page_Load sull'ascx.

Markup ASCX

    

codice dietro

CPCalendarCell di classe pubblica     Eredita 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

Fine classe

markup della pagina ASPX

     

codice dietro l'evento Calendar DayRender nel modulo

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

Per il ciclo di vita della pagina asp.net i tuoi controlli non sono completamente aggiunti in pre-rendering, perché non carichi semplicemente i valori in page_load?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top