ASP.NET is teh st00pid.

StageLeft

No Lifer
Sep 29, 2000
70,150
5
0
What a PAIN IN THE ASS it is playing with dynamically created controls. I've got a page with a menu up top of dynamically created link buttons, which in turn fill a datagrid with yet more linkbuttons, and of course the paging for the datagrid is composed of linkbuttons.

Given that the handling for these has to occur prior to the end of page load, and the events of a linkbutton (or any control) occur AFTER the page_load, if you want to have a control's event create other controls and you expect them to be tied in with event handling, the only way is to have them set some flags or crap and then essentially reload your page, requiring another post back.

What I've done now is create a class within my page which has all of my form values (about 9 different search criteria). When a link button clicks it sets the class's properties with my form values, then just transfers back to the page where page load checks this class (which is stored in a session object).

I suppose my real problem here is that a linkbutton acts as a control, and not as a hyperlink with an onclick event (which you see a lot of pages use these days, so that you can set some hidden form fields on a page, then submit it, and then their values are available immediately on page load).
 

oog

Golden Member
Feb 14, 2002
1,721
0
0
why can't you wire up the events after you create the controls? there's no reason you can't register an event handler in the same code that creates the control. Use AddHandler in VB .NET or "control.eventname +=" in C#.
 

StageLeft

No Lifer
Sep 29, 2000
70,150
5
0
Originally posted by: oog
why can't you wire up the events after you create the controls? there's no reason you can't register an event handler in the same code that creates the control. Use AddHandler in VB .NET or "control.eventname +=" in C#.
You can and it will execute, but it won't work. If you have, for instance, a button click and that click produces a bunch of linkbuttons, and then uses addhandler on them, yes the code will run. Also, the linkbuttons will be created on your screen. They will be serverside with a postback, but they will not trigger that event handler. The screen will just flash as it posts back a mindless control. The addhandler execution has to happen no later than form_load, and since this linkbutton-creating button click is occuring after the form load (since FL always happens prior to control events), the addhandler statement is useless and pointless.

So, in conclusion, there is absolutely zero point in using addhandler to wire up events of dynamic controls in another control's event, because it won't work. Those new dynamic controls simply will not function. So, if you make hyperlinks that's fine, since they're client side. But, if you're making server side dynamic controls you basically have to set some dumbass flag and have yet another postback after the flag is set in your control event, so that Form_load will know to make the controls, NOT, your control-creating button click (or whatever you should choose).

 

StageLeft

No Lifer
Sep 29, 2000
70,150
5
0
Well a guy at work directed me on how to get around this. I decided that my form values in a session and everything else was an ungodly mess, so I was going to make some HTML links and mimic linkbutton functionality, except that they would set what they need to in hidden fields and submit the form, meaning that form load has what it wants the first time.

However, in form_load in .net even with any other control you can do a request.item("__EVENTTARGET") and get the ID of the calling control before its event fires. As it is now the ID is the only damn thing I need, so I'm going to make my dynamic controls, forget their event handling altogether, and simply process right within form load based on the returning ID of each control.
 

oog

Golden Member
Feb 14, 2002
1,721
0
0
You're right. I forgot that the controls would not be recreated in the page_init so they wouldn't know to fire their events. I created a small test page, and it looks like if you do set a flag that tells you that dynamic controls were created, you can recreate the same controls again in page_init, and their corresponding events will fire correctly. It does not require an additional reload of the page -- just an explicit recreation of the controls so that they exist to fire the events. This may still be more trouble than it's worth though.
 

oog

Golden Member
Feb 14, 2002
1,721
0
0
If you do try recreating the controls, make sure they have an ID so that the incoming post can match up the event with the control correctly.
 

StageLeft

No Lifer
Sep 29, 2000
70,150
5
0
Originally posted by: oog
You're right. I forgot that the controls would not be recreated in the page_init so they wouldn't know to fire their events. I created a small test page, and it looks like if you do set a flag that tells you that dynamic controls were created, you can recreate the same controls again in page_init, and their corresponding events will fire correctly. It does not require an additional reload of the page -- just an explicit recreation of the controls so that they exist to fire the events. This may still be more trouble than it's worth though.
Do you have an example of the syntax to do that as cleanly as possible? I have to say that since I've decided to stop bothering with event handling on these dynamic controls my page is quicker and about 1/4 the code of before. It's really quite superb. I've just got some if/elses in the form_load, which are executing logic based on the Request.Item("__EVENTTARGET"). I've gone from a whole bunch of junk down to that and a couple of viewstate variables!

 

oog

Golden Member
Feb 14, 2002
1,721
0
0
Here is the code I wrote:

using System;

namespace DynamicControl
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder1;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
if (IsPostBack)
{
object viewStateValue = ViewState["createcontrols"];
if (viewStateValue != null && viewStateValue.ToString() == "true")
{
CreateControls();
}
}
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion

private void Button1_Click(object sender, System.EventArgs e)
{
CreateControls();
}

private void CreateControls()
{
System.Web.UI.WebControls.Button button = new System.Web.UI.WebControls.Button();
PlaceHolder1.Controls.Add(button);
button.Click += new EventHandler(DynamicButton_Click);
button.Text = "second button";
ViewState["createcontrols"] = "true";
}

private void DynamicButton_Click(object sender, System.EventArgs e)
{
TextBox1.Text = "dynamic button clicked";
}
}
}

Sorry for the loss of indentation. The web page itself has a button, a textbox and a placeholder. A second button is created dynamically, and the dynamic button's event handler sets the text in the textbox. I just use ViewState to store the fact that the button needs to be recreated. I also found that as long as the controls are created in Page_Load, it's still in plenty of time for the event handling to work. If you're happy with the approach you took, there's no problem in continuing with what you have. You'll always find there's more overhead with creating these extra objects (the controls) and firing events. I haven't found it to be a lot more time, but the overhead is definitely there.