0

Down and to the point question. I am having a miserable time with some dynamically created buttons. They do not want to fire the Click event I have setup for them. A paraphrase of my code is below. Could anyone provide some insight as to why my dynamic controls do not work?

protected void Page_Load(object sender, EventArgs e)
{
    CreateButton();
}
private void CreateButton()
{
    Button btn = new Button();
    btn.ID = "Button1";
    btn.Click += Button1_Click;

    panel1.Controls.Add(btn);
}

protected void Button1_Click(object sender, EventArgs e)
{
    // Do stuff here.
    // Debugger never makes it to this point.
}

I have this current functionality. It needs to be able to graphically reorder, remove and add items.

enter image description here

Volearix
  • 1,573
  • 3
  • 23
  • 49
  • what do you mean when you say "They do not want to fire the Click Event you have setup.. how do they know what you have setup.. please be more clear on what you are trying to accomplish.. read this article as well http://www.4guysfromrolla.com/articles/092904-1.aspx – MethodMan Aug 21 '14 at 20:08
  • Having just read the title, I can already tell you that the solution is to just not use dynamic ASP controls. They're a nightmare. – Servy Aug 21 '14 at 20:08
  • @Servy How could I generate a button based on an array of items then? Any suggestions because I would love to be able to avoid them. – Volearix Aug 21 '14 at 20:10
  • @Volearix Use a `Repeater`. – Servy Aug 21 '14 at 20:11
  • They are for sure not trivial to handle, but I was working in a project with lots of dynamic controls, because it was really our requirement to generate them in runtime. It's a very powerful approach, but for sure you have to do it right. – the berserker Aug 21 '14 at 20:12

2 Answers2

1

Just...don't use dynamic ASP controls. Ever. They're super hard to work with, and there are superior alternatives.

If you want to create a dynamic number of controls based on some data that you have use a Repeater, or, if you want to create a table of data specifically, a DataGrid. These have sensible behaviors and are far easier to work with.

If you have content that you want to optionally render, for example a single fixed button that may or may not need to be shown, then define that control in markup and use the Visible property to determine if it is actually send to the end user.

As for why it doesn't work, ASP has many steps in a page's lifecycle. One of the early steps is to initialize it's view of the page with all of the items on it. At a later point in time the post back data is inspected, any events triggered find their corresponding control in the view of the page, and then run the corresponding handlers for that event. In your case you're creating the control and adding the handlers after the request's "page view" has already been finalized. The code didn't see your button, or any handlers for it, so it didn't have any handlers to run.

This is all complicated further if the creation of your dynamic controls are dependent on information being posted back from the user (which does in fact appear to be the case here). If you create the controls early enough in the lifecycle for them to be able to fire events, then the information that you need to get from what the user has just done hasn't yet been populated into their corresponding ASP constructs. You end up being forced to construct the dynamic objects before you actually have access to the information to construct them.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • I am looking at repeaters, would I be able to create an interface such as the image provided with a repeater? – Volearix Aug 21 '14 at 20:16
  • @Volearix Yes, you could, and it would be *far* easier than trying to use dynamic controls. – Servy Aug 21 '14 at 20:18
  • Okay, so do you have a good source/example of how I could possibly achieve this. I am completely unfamiliar with the use of repeaters and they look to be complicated from everything I see. – Volearix Aug 21 '14 at 20:28
  • @Volearix There are tons and tons of tutorials on using repeaters out there to choose from. The idea is simple though; create a template of what one single item looks like in markup, and then bind your data with some number of different items to the repeater, which will apply the template to each of your items. – Servy Aug 21 '14 at 20:41
  • Repeater worked, took some time to understand the idea, but exactly what I needed. – Volearix Aug 26 '14 at 20:01
0

Page_Load is probably already too late to do that and in ASP.NET lifecycle there is a CreateChildControls method that you should use to create controls dynamically.

Frequent problems with dynamically generated controls and events not being fired are (Edit: the 2nd bullet is probably your issue, since you mention reordering of controls; also as you submitted the picture, repeater seems better idea, as it was proposed by Servy):

  • if you forget to assign the ID to the control, ASP.NET can generate different ID to the control on the client and the handlers will not be invoked on server (you have that covered)
  • if the hierarchy of the controls changes on postback, ASP.NET will not be able to find a control in the control tree and therefore not invoke the handler again (controls on server are matched by index instead by name!). You can compare the page trace of control tree between 1st render of the page and postback. You should assure that the control tree is not different between postbacks (e.g. you should not skip adding controls to the page on postback, but rather include them in the control tree, but not display them).
Community
  • 1
  • 1
the berserker
  • 1,553
  • 3
  • 22
  • 39