Event binding in dynamically loaded user controls

I am creating a test project to demonstrate (to me) how to dynamically load user controls. Everything works except for wiring the control to notify the parent that something has happened. The problem is with the line that is trying to associate the event in the user control with the event handler on the parent page. The "NotifyParentEvent" event is not displayed and the compiler runs on it (the event is not defined in System.Web.UI.Control). I tried using UserControl instead of Control, but to no avail.

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

User Management Code:

 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(); } } } 
+4
source share
2 answers

Option 1

You need to pass you a control that implements the NotifyParentEvent event to attach an event handler. Basically, in your ReloadControl method ReloadControl replace this line of code:

 control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler); 

with the following:

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

Option 2

A more general approach was to create an interface and check if this dynamic control implements this interface.

Create an interface:

 interface INotifyParent { event CommandEventHandler NotifyParentEvent; } 

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

Check if the dynamic control implements the interface:

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

Try applying the control to the appropriate type before adding an event handler.

I'm not sure if this will work, but try casting using a dynamic type rather than Control.

aka

 dynamic control = Page.LoadControl(SavedControlVirtualPath); 

This code assumes you are using .NET 4.0

0
source

All Articles