Dynamically loaded user control event subscribing
I am having a very hard time subscribing to events in a dynamically loaded user control. It's probably easiest to just look at the code I am having trouble with. Any help is greatly appreciated.
On the parent page I use this method to dynamically load user controls.
private void LoadMyUserControl(string controlName)
{
parent.Controls.Clear();
// Load the user Control
UserControl MyControl = (UserControl)LoadControl(ControlName);
string userControlID = controlName.Split('.')[0];
MyControl.ID = userControlID.Replace("/","").Replace("~", "");
Type ucType = MyControl.GetType();
// Set misc parameters
PropertyInfo myProp = ucType.GetProperty("MyProp");
myProp.SetValue(MyControl, "MyVal", null);
//Dynamically subscribe to user control event
Type objectType = MyControl.GetType();
EventInfo objectEventInfo = objectType.GetEvent("updateParent");
Type objectEventHandlerType = objectEventInfo.EventHandlerType;
MethodInfo mi = this.GetType().GetMethod("HandledEvent");
Delegate del = Delegate.CreateDelegate(objectEventHandlerType, this, mi);
objectEventInfo.AddEventHandler(this, del);
}
public void HandledEvent (Object sender, EventArgs e)
{
}
My user control has a simple public event like this
public partial class MyUserControl1 : System.Web.UI.UserControl
{
public int MyProp { get; set; }
public event EventHandler up开发者_如何学运维dateParent;
}
The error I am getting is on the ObjectEventInfo.AddEventHandler line stating "Object does not match target type."
Thanks again in advance for your assistance.
Solution #1: Create a common interface.
// IParentControlUpdater.cs
namespace AspNetUserControlDynamicEvent {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
interface IParentControlUpdater {
event EventHandler<EventArgs> UpdateParent;
}
}
// DynamicUserControl.ascx.cs
namespace AspNetUserControlDynamicEvent {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class DynamicUserControl : System.Web.UI.UserControl, IParentControlUpdater {
protected void Page_Load(object sender, EventArgs e) { }
#region IParentControlUpdater Members
public event EventHandler<EventArgs> UpdateParent;
#endregion
}
}
// Default.aspx.cs
namespace AspNetUserControlDynamicEvent {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) { }
private void LoadMyUserControl(string controlName) {
UserControl control = (UserControl)LoadControl(controlName);
// Do some stuff
((IParentControlUpdater)control).UpdateParent += new EventHandler<EventArgs>(control_UpdateParent);
}
private void control_UpdateParent(object sender, EventArgs e) {
throw new NotImplementedException();
}
}
}
Solution #2: Create a base class. Create a base user control class (ie. DynamicUserControlBase for example).
// DynamicUserControlBase.ascx.cs
namespace AspNetUserControlDynamicEvent {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class DynamicUserControlBase : System.Web.UI.UserControl {
protected void Page_Load(object sender, EventArgs e) { }
// Base event
public event System.EventHandler<System.EventArgs> UpdateParent;
}
}
Then in your user control's you want to dynamically create and subscribe the updateParent event:
// DynamicUserControl.ascx.cs
namespace AspNetUserControlDynamicEvent {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class DynamicUserControl : DynamicUserControlBase {
protected void Page_Load(object sender, EventArgs e) { }
}
}
Note how it inherits from DynamicUserControlBase. Now, for your LoadMyUserControl method:
private void LoadMyUserControl(string controlName) {
DynamicUserControlBase control = (DynamicUserControlBase)LoadControl(controlName);
// Do some stuff
control.UpdateParent += new EventHandler<EventArgs>(HandledEvent);
}
private void HandledEvent(object sender, EventArgs e) {
throw new NotImplementedException();
}
However, if you are only working with one type of control you could just as easily change the boxing on LoadControl to:
WebUserControl1 control = (WebUserControl1)LoadControl(controlName); // example
But it seems as though you are possibly looking at loading many different types of user controls, so the first solution should work fine.
As for your concern via Reflection, try this:
Type type = MyControl.GetType();
EventInfo eventInfo = type.GetEvent("UpdateParent");
EventHandler handler = new EventHandler(HandledEvent);
eventInfo.AddEventHandler(MyControl, handler);
If you want to get a generic solution, you could create an abstract user control class with your property and your event. Then MyUserControl1 can inherit from this abstract user control. In your load method you can cast to the abstract user control and use it in an easier way. So you could create some other user controls.
精彩评论