动态加载的用户控件事件订阅

时间:2011-07-11 19:56:26

标签: c# asp.net 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)
  {

  }

我的用户控件有一个像这样的简单公共事件

  public partial class MyUserControl1 : System.Web.UI.UserControl
  {
         public int MyProp { get; set; }
         public event EventHandler updateParent;
  }

我得到的错误是在ObjectEventInfo.AddEventHandler行上,说明“对象与目标类型不匹配。”

再次感谢您的协助。

2 个答案:

答案 0 :(得分:1)

如果要获得通用解决方案,可以使用属性和事件创建抽象用户控件类。然后MyUserControl1可以从这个抽象用户控件继承。在您的加载方法中,您可以转换为抽象用户控件并以更简单的方式使用它。所以你可以创建一些其他用户控件。

答案 1 :(得分:1)

解决方案#1:创建一个通用界面。

// 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();
        }
    }
}

解决方案#2:创建基类。 创建一个基本用户控件类(例如,DynamicUserControlBase)。

// 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;
    }
}

然后在您的用户控件中,您想要动态创建和订阅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 : DynamicUserControlBase {
        protected void Page_Load(object sender, EventArgs e) { }
    }
}

注意它是如何从DynamicUserControlBase继承的。现在,为您的LoadMyUserControl方法:

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

但是,如果您只使用一种类型的控件,您可以轻松地将LoadControl上的装箱更改为:

WebUserControl1 control = (WebUserControl1)LoadControl(controlName); // example

但似乎您可能正在考虑加载许多不同类型的用户控件,因此第一个解决方案应该可以正常工作。

关于您对Reflection的关注,请尝试以下方法:

Type type = MyControl.GetType();
EventInfo eventInfo = type.GetEvent("UpdateParent");
EventHandler handler = new EventHandler(HandledEvent);
eventInfo.AddEventHandler(MyControl, handler);