2011-07-20 5 views
4

Je suis en train de construire un projet de test pour démontrer (à moi) comment charger dynamiquement les contrôles utilisateur. Tout fonctionne sauf le câblage du contrôle pour informer le parent que quelque chose s'est passé. Le problème est avec la ligne qui essaie de connecter l'événement dans le contrôle utilisateur au gestionnaire d'événements dans la page parent. L'événement "NotifyParentEvent" n'est pas visible et le compilateur l'affiche (l'événement n'est pas défini dans System.Web.UI.Control). J'ai essayé d'utiliser UserControl au lieu de Control, mais en vain.Liaison aux événements dans les contrôles utilisateur chargés dynamiquement

Control control = Page.LoadControl(SavedControlVirtualPath); 
if (control != null) 
{ 
    control.ID = control.GetType().Name; 
>>>>> control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
    controlPlaceholder.Controls.Add(control); 
} 

code derrière pour le contrôle de l'utilisateur:

public partial class UserControls_WebUserControl1 : System.Web.UI.UserControl 
{ 
    public event CommandEventHandler NotifyParentEvent; 

    private void NotifyParent(string message) 
    { 
     if (NotifyParentEvent != null) 
     { 
      CommandEventArgs e = new CommandEventArgs("Control1 Action", message); 
      NotifyParentEvent(this, e); 
     } 
    } 
} 

Parent Page:

public partial class _Default : System.Web.UI.Page 
{ 
    private string SavedControlVirtualPath 
    { 
     get {return (ViewState["savedControlPath"] == null || (string)ViewState["savedControlPath"] == string.Empty) 
       ? null : (string)ViewState["savedControlPath"]; } 
     set { ViewState["savedControlPath"] = value; } 
    } 

    private void ReloadControl() 
    { 
     controlPlaceholder.Controls.Clear(); 
     if (SavedControlVirtualPath != null) 
     { 
      Control control = Page.LoadControl(SavedControlVirtualPath); 
      if (control != null) 
      { 
       // Gives the control a unique ID. It is important to ensure 
       // the page working properly. Here we use control.GetType().Name 
       // as the ID. 
       control.ID = control.GetType().Name; 
       control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); <== THIS LINE WON'T COMPILE 
       controlPlaceholder.Controls.Add(control); 
      } 
     } 
    } 

    private void UserControlNotificationHandler(object sender, CommandEventArgs e) 
    { 
     // ??? 
    } 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += "Page_Init<br />"; 
     LoadUserControls(); 
    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += string.Format("{0} on main page<br />", (this.IsPostBack) ? "Postback" : "Page_Load"); 
     ReloadControl(); 
    } 

    protected void rblControlSelector_Changed(object sender, EventArgs e) 
    { 
     lblLastEvent.Text += "rblControlSelector_Changed<br />"; 
     LoadUserControls(); 
    } 

    private void LoadUserControls() 
    { 
     Label lbl = new Label(); 
     controlPlaceholder.Controls.Clear(); 
     switch (rblControlSelector.SelectedValue) 
     { 
      case "0": 
       lblLastEvent.Text = "Unload/Clear<br />"; 
       SavedControlVirtualPath = ""; 
       break; 

      case "1": 
       lblLastEvent.Text += "Adding control #1<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl1.ascx"; 
       break; 

      case "2": 
       lblLastEvent.Text += "Adding control #2<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl2.ascx"; 
       break; 

      case "3": 
       lblLastEvent.Text += "Adding control #3<br />"; 
       SavedControlVirtualPath = "~/UserControls/WebUserControl3.ascx"; 
       break; 

     } 
     if (!string.IsNullOrEmpty(SavedControlVirtualPath)) 
     { 
      ReloadControl(); 
     } 
    } 
} 
+0

modifié ma question ci-dessous, laissez-moi savoir si ça aide –

Répondre

4

Option 1

Vous devez vous rejetterai contrôler à un type qui implémente l'événement NotifyParentEvent pour attacher le gestionnaire d'événement. En fait, dans votre méthode ReloadControl, remplacez cette ligne de code:

control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 

ce qui suit:

if(control is UserControls_WebUserControl1) 
{ 
    (control as UserControls_WebUserControl1).NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
} 

Option 2

Une approche plus générique serait de créer une interface et vérifiez si le contrôle dynamique implémente cette interface.

Création de l'interface:

interface INotifyParent 
{ 
    event CommandEventHandler NotifyParentEvent; 
} 

implémentent l'interface:

public partial class UserControls_WebUserControl1 : System.Web.UI.UserControl, INotifyParent 
{ 
    public event CommandEventHandler NotifyParentEvent; 

    private void NotifyParent(string message) 
    { 
     if (NotifyParentEvent != null) 
     { 
      CommandEventArgs e = new CommandEventArgs("Control1 Action", message); 
      NotifyParentEvent(this, e); 
     } 
    } 
} 

Vérifiez si le contrôle dynamique implémente l'interface:

if(control is INotifyParent) 
{ 
    (control as INotifyParent).NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 
} 
+0

Je vais essayer ceci, mais cette solution nécessite que je connaisse le nom de classe de chaque contrôle. J'ai besoin d'une solution générale qui déterminera dynamiquement dans l'événement NotifyParentHandler est définie, et si c'est le cas, raccordez-le. –

+0

Vous devez ensuite créer une interface qui expose l'événement et dont les contrôles implémentent l'interface. De cette façon, vous pouvez convertir le type d'interface plutôt qu'un type de contrôle concret. Il peut également être judicieux d'utiliser une classe de base qui implémente l'événement afin que vous n'ayez pas à dupliquer le code dans chaque contrôle. –

+0

Grâce à l'article de Vassili et Tim Stall (http://www.4guysfromrolla.com/articles/110304-1.aspx), j'ai eu ce travail. Il a fallu quelques ajustements, mais si quelqu'un veut le code source, faites le moi savoir. –

0

Essayez casting le contrôle de son type approprié avant d'ajouter le gestionnaire d'événements.

Je ne suis pas sûr que cela fonctionnera, mais essayez de lancer en utilisant le type dynamique plutôt que de contrôle.

aka

dynamic control = Page.LoadControl(SavedControlVirtualPath); 

Ce code suppose que vous utilisez .NET 4.0

+0

Étant donné que c'est un contrôle chargé dynamiquement, je ne sais pas quel type est approprié. Pouvez-vous me donner un exemple du code auquel vous songez? Je soupçonne que cela puisse nécessiter une «réflexion» que je ne comprends pas encore. –

Questions connexes