我正在构建一个测试项目来演示(对我来说)如何动态加载用户控件。除了将控件连接到通知父控件发生了某些事情之外,其他一切都工作正常。问题在于试图将用户控件中的事件连接到父页面中的事件处理程序的行。"NotifyParentEvent"事件是不可见的,编译器会停止运行(该事件没有在System.Web.UI.Control中定义)。我试过用UserControl代替Control,但是没有用。
Control control = Page.LoadControl(SavedControlVirtualPath);
if (control != null)
{
control.ID = control.GetType().Name;
>>>>> control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler);
controlPlaceholder.Controls.Add(control);
}
用户控件背后的代码:
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);
}
}
}
父页面: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();
}
}
}
选项1
您需要将控件强制转换为实现NotifyParentEvent事件的类型,以便附加事件处理程序。基本上,在您的ReloadControl
方法中,替换这行代码:
control.NotifyParentEvent += new EventHandler(UserControlNotificationHandler);
与以下内容:
if(control is UserControls_WebUserControl1)
{
(control as UserControls_WebUserControl1).NotifyParentEvent += new EventHandler(UserControlNotificationHandler);
}
选项2
更通用的方法是创建一个接口,并检查动态控件是否实现了该接口。
创建接口:
interface INotifyParent
{
event CommandEventHandler NotifyParentEvent;
}
实现接口:
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);
}
}
}
检查动态控制是否实现了接口:
if(control is INotifyParent)
{
(control as INotifyParent).NotifyParentEvent += new EventHandler(UserControlNotificationHandler);
}
在添加事件处理程序之前尝试将控件转换为适当的类型。
我不确定这是否会起作用,但尝试使用动态类型而不是Control。
又名
dynamic control = Page.LoadControl(SavedControlVirtualPath);
此代码假设您使用的是。net 4.0