开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜