绑定到动态加载的用户控件中的事件

时间:2011-07-20 20:41:03

标签: c# dynamic user-controls event-handling

我正在构建一个测试项目来演示(对我来说)如何动态加载用户控件。一切正常,除了控件的布线,以通知父母已发生的事情。问题在于尝试将用户控件中的事件连接到父页面中的事件处理程序的行。 “NotifyParentEvent”事件不可见,并且编译器barfs(事件未在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();
        }
    }
}

2 个答案:

答案 0 :(得分:4)

选项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);
}

答案 1 :(得分:0)

在添加eventhandler之前,尝试将控件转换为正确的类型。

我不确定这会有效,但尝试使用动态类型而不是控件进行投射。

又名

dynamic control = Page.LoadControl(SavedControlVirtualPath);

此代码假定您使用的是.NET 4.0