views:

590

answers:

6

I have a Control I want to create. Here's a simple example of what I was to accomplish.

I want the control to contain a button.

Button b = new Button();
b.Text = "Test";
b.Click += new EventHandler(b_Click);

this.Controls.Add(b);

Now, the control renders fine, the button shows up on the page. The heart of the problem I'm having is that the b_Click Event Handler is never triggered.

protected void b_Click(object sender, EventArgs e)
{
    throw new NotImplementedException();
}

Any help here would be much appreciated. I don't want to use a User Control here for purely selfish reasons and would like to totally encapsulate this in a single DLL.

Thanks In Advance.

EDIT**

namespace ClassLibrary1
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
    public class WebCustomControl1 : WebControl
    {

     protected override void CreateChildControls()
     {
      Button b = new Button();
                    b.ID = "button";
      b.Text = "Click Me";
      b.Click += new EventHandler(b_Click);

      this.Controls.Add(b);

      base.CreateChildControls();
     }

     protected void b_Click(object sender, EventArgs e)
     {
      this.Controls.Add(new LiteralControl("<p>Click!</p>"));
     }

    }
}

So from the comments I've tried this. The simplest of exampes, still no go. Is there something I'm fundamentally missing?

A: 

So your button renders to the page correctly and causes a postback when the user clicks it, but the OnClick code never runs?

Remember, whenever you do a postback you're working with a brand new instance of your page class. Part of the postback process is running whatever event was triggered by the user. For this to happen, the asp.net processor needs to know about the event at a specific point in the page lifecycle. At this point, your button must already be on the page with the event handler registered. If this doesn't happen, your event won't fire. Try moving your button creation up earlier in the page lifecycle.

Joel Coehoorn
A: 

This may be the case of assigning the handlers well after the event is raised.

My common practice when dealing with controls are:

  1. Use Control.Init event to initialize everything (default text, handlers, size, composition, etc.) and also initialize the child controls.
  2. Use Control.Load event to handle any data binding operation (based on the properties/fields set during the Init event).
Adrian Godong
+3  A: 

Override the CreateChildControls method and create/add the button (and register the handler) in that method.

Using OnInit/OnLoad to create controls like this is incorrect and will lead to inconsistent behavior (such as what you're experiencing).

Edit: You might also try setting button.ID so that it's the same on every postback, it's possible the raised event isn't seeing it for that reason.

technophile
CreateChildControls is called during the Control.Init event. While overriding OnInit may be wrong (depends on what you are trying to do), handling Control.Init is not. And don't forget to call base.CreateChildControls to make sure that your base classes are initialized properly.
Adrian Godong
CreateChildControls *may* be called during Control.Init. However, it can be called from other places as well (EnsureChildControls may be called at any point).
technophile
+1  A: 

Please show the definition of your control class.

Does your control inherit from Control, WebControl, or CompositeControl. Try inheriting from CompositeControl and see if that helps.

John Saunders
A: 

Check the identifier of the button control before the postback and after the postback. If it's not the same, it won't work.

You can overwrite the identifier yourself if needed.

GoodEnough
+4  A: 
public class WebCustomControl1 : WebControl

needed to be

public class WebCustomControl1 : WebControl, INamingContainer

that's it. that's all that was needed to make this postback issue work.

Aaron
nice work !!! Keep on doing
anishmarokey
That's all I needed - had the same problem
Keith