2008-10-27 8 views
15

J'ai un problème lors de l'utilisation LoadControl(type, Params). Laissez-moi vous expliquer ...Asp.net Usercontrol LoadControl Problème

J'ai un contrôle utilisateur super 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" /> 

avec le code (C#) derrière 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; 
     } 
    } 
} 

Ailleurs dans mon application Web J'ajoute une instance de la usercontrol à la page en utilisant le code suivant:

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

J'utilise la version surchargée de LoadControl parce que je veux passer le paramètre Message au constructeur. Tout cela apparaît pour fonctionner correctement.

Cependant, lorsque le OnPreRender() est déclenché sur le contrôle utilisateur ErrorDisplay, les variables lblTitle et lblDescription sont toutes les deux null, bien qu'elles aient un balisage équivalent. La variable de message a été correctement renseignée.

Quelqu'un peut-il faire la lumière sur la raison pour laquelle cela peut se produire?

Merci

EDIT:

Juste pour plus de clarté, je vais aussi ajouter que le code qui ajoute programatically UserControl à la page est en cours d'exécution en réponse à une pression sur un bouton, de sorte que le « hébergement page 'a progressé dans Init, Page_Load et traite maintenant les gestionnaires d'événements.

Je ne peux pas ajouter les usercontrols à un stade du cycle de vie asp plus tôt car ils sont créés en réponse à un bouton événement click.

Répondre

19

J'ai essayé le code suivant ainsi - ce qui donne le même résultat (à savoir les deux lblTitle et lblDescription sont nuls)

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

j'avais entendu que la fonction LoadControl a le contrôle, il se charge jusqu'à l'état actuel de la page sur laquelle elle est incluse. par conséquent, l'initialisation, Page_Load, etc. sont tous exécutés dans le cadre de l'appel LoadControl.

Fait intéressant ce (sans réponses) forums asp.net publier des expositions le même problème que je ressentais.

MSDN Forums Post

De plus - De MSDN:

Lorsque vous chargez un contrôle dans un contrôle conteneur, le conteneur soulève tous les événements du contrôle ajouté jusqu'à ce qu'il ait rattrapé l'événement en cours. Cependant, le contrôle ajouté ne rattrape pas le traitement des données de publication.Pour qu'un contrôle supplémentaire participe au traitement des données de publication, y compris la validation, le contrôle doit être ajouté dans l'événement Init plutôt que dans l'événement Load.

Par conséquent, LoadControl ne devrait-il pas correctement initialiser le contrôle?

EDIT:

Ok, donc je réponds à ma propre question ici ..

Je trouve une version réponse du poste de forum je lien ci-dessus Here

Essentiellement la réponse est que le LoadControl(type, params) ne peut pas déduire la page 'infront' ascx pour analyser et donc il ne dérange pas initier l'un des contrôles. Lorsque vous utilisez la version LoadControl("ascx path"), il est donné la page en face et donc fait tout l'analyse et initalision. Donc, en résumé, j'ai besoin de changer le code qui initie le contrôle et le diviser en parties séparées. C'est à dire.

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

Et cela devrait fonctionner correctement .. Ce n'est pas aussi soigné que mon essai précédent, mais au moins cela fonctionnera.

Je suis toujours ouvert aux suggestions pour améliorer ce qui précède.

Vive

+3

+1 et une note de remerciement de ma part pour résoudre le problème que j'avais. :) –

+0

Excellent suivi! –

-1

par le cycle de vie de page asp.net vos contrôles ne sont pas entièrement ajoutés dans Prérendu, pourquoi ne pas charger seulement les valeurs page_load?

+1

Ce n'est pas correct. [PreRender se produit après chargement.] (Http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events) 'déclenché après que l'objet Page a créé tous les contrôles – Chris

0

D'accord avec Mitchel, vous devriez être en mesure de mettre un page_load dans le code de contrôle lui-même qui se déclenche après que les contrôles sont complètement disponibles.

+1

[PreRender arrive * après * Load] (http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events), donc PreRender devrait être sûr. – Chris

0

Eh bien, il y a toujours ajouter votre propre événement de charge et de l'appeler après avoir couru le constructeur et a ajouté le contrôle à la page, mais ce n'est pas très différent de ce que vous avez, bien que je pourrais choisir pour des raisons de style.

Content de trouver une réponse à votre problème!

0

Here est un article écrit par Steven Robbins. Le message explique comment passer des paramètres pour un contrôle utilisateur à l'aide LoadControl, semblable à ce que LoadControl(Type, object[]) ferait, sauf qu'il fonctionne :)

0

J'ai eu un problème similaire avec l'événement DayRender de contrôle du calendrier, en ce que je voulais ajouter un contrôle utilisateur à la collection e.Cell.Controls. Après avoir essayé quelques approches échouées avec le contrôle utilisateur page_load ne tirant pas ou la listbox sur l'ASCX rejetant une exception nulle, j'ai trouvé que si j'initialisé mon contrôle sur le formulaire avec LoadControl (ascx), puis commencer à accéder aux contrôles de balisage sur le ascx, tout a bien fonctionné. Cette approche ne dépend pas de l'événement Page_Load sur l'ascx.

ASCX balisage

code derrière

Classe publique CPCalendarCell Hérite 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 

End Class

page ASPX balisage

Code

derrière le calendrier événement DayRender sur le formulaire

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 
Questions connexes