dynamically created control event handling


Essentially I have a placeholder added to the page dynamically on page load.

Then I have a composite control that is added to the placeholder and displayed during runtime for specific page events. The composite control has a button. I have a public eventhandler for the button available in the composite control, but don't actually have direct access to this eventhandler in the page code.

To display the control, I would make the following call for example:

MyControl.Create(args, new EventHandler(OnClick)); 

Then on the page I would have protected void OnClick(object o, EventArgs args) {}

Of course when I call create() I wire up my eventhandler to the composite control's button click event. So far so good. With the button wired, the button click posts back to the control as expected. However, the event never makes it back to the page's event handler.

I realize the problem is occurring on postback. Yet, attempting to wire the button on init, load or createchildcontrols all fail to keep the wiring in place so the event can be handled on the page. What I would like, is the ability to pass the eventhandler to the composite control during runtime, and for the composite control to send the event correctly back to the page on postback.

Interestingly, if I call OnBubble with custom eventargs I can catch the bubbled event on the page. But the problem is that my placeholder is on the page, so when I attempt to call MyControl.Create() in a UserControl, for example, the bubble goes to the page and not to the UserControl (as expected). Hence, the reason I prefer to declare the eventhandler instead of overriding OnBubble (UserControls and other controls that declare MyControl would essentially render it useless for button click events).

I'm hoping someone has some insight into the problem. It seems like an interesting problem, but perhaps there is no solution outside of declaring the control explicitly on the page, and directly wiring up the event either in the markup or on pageload. I would consider having the button make an asynchronous callback, but would prefer to use standard ASP.NET event handling if possible.


To add clarification: the MyControl.Create() call actually generates an event that calls the Composite Control's Create() method. this is all well and good, but it is worth noting that the MyControl.Create() method does not have direct access to the control. This should make sense because the the control is added to the page onload on not in markup.

More Code:

MyControl : CompositeControl 
     public event EventHandler Click;

     //I have a create method
     void Create(args, EventHandler click)
          this.Click = click;
          //other processing

     //then the button is wired up. I've tried in OnInit(), OnLoad()
     void CreateChildControls()
           MyButton.OnClick += Click;

     //if I wire up the button to a default handler I can check if
       Click is not null and send the click event onto the next handler 
     //this is where the bubble event works, but the wiring fails

Edit: My attempt to store the eventhandler in the Session and wire up the button on postback was successful. I don't consider this good practice, and I don't think it actually serves my purpose. For example, in this case the event on the page executes as expected, but with non-standard page behavior. For example, Response.Redirect() throws an exception. This should make sense because the eventhandler has probably lost state information during the postback.
A couple of thoughts:
1. Is it possible that I could create a custom bubble event that is somehow related to this control? This seems plausible, but again the problem of the page postback leaves me with the same problem of where the bubble should go. So, when I call create(), is it possible that I can automagically register the UserControl as the destination for the bubble? It seems difficult.
2. Is there some point in the page lifecycle where I can re-wire the event on the UserControl declared eventhandler so that the delegate is called correctly on postback? This seems to be what I am missing. The eventhandler is created on a postback, but is lost because it is not re-created in the UserControl during OnClick. I don't want the UserControl to have to explicitly re-create the thing, but want the child control to re-create it for the UserControl. It sounds like a simple request, but with the UserControl out of the loop, I may be asking for the impossible.

Best Solution

You have not specifically mention at which point of the page lifecycle do you create and add those controls. For the postback to work, all the creation(and wiring) and 're-creation' has to be done before page_load event.

Do it at page_init and the viewstate mechanism should take over the postback values if the IDs are the same.

I've come across another method here though:

Related Question