Dynamic Button with Event

  • Thread starter Thread starter Mr Not So Know It All
  • Start date Start date
M

Mr Not So Know It All

I've new to .NET. I'm trying to add a button dynamically with an
event. Initially, I have a button with a click. The original button's
click event response writes a test message and adds a button. The new
button has a click event attached with a test message. Unfortunately,
when I click the dynamically attached button, nothing happens. Could
someone walk me throught this?

[aspNET:CODE]
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="plh" runat="server">
<asp:Button ID="btn_Click" Text="Click" runat="server" />
</asp:PlaceHolder>
</div>
</form>
</body>
</html>

CODEFILE
public partial class dynamicEvent : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click +=new EventHandler(Clicked);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("Button One Clicked");
Button btn = new Button();
plh.Controls.Add(btn);
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("Dynamic Button Clicked");
}
}
[/aspNET:CODE]
 
Mr Not So Know It All said:
I've new to .NET. I'm trying to add a button dynamically with an
event. Initially, I have a button with a click. The original button's
click event response writes a test message and adds a button. The new
button has a click event attached with a test message. Unfortunately,
when I click the dynamically attached button, nothing happens. Could
someone walk me throught this?

[aspNET:CODE]
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="plh" runat="server">
<asp:Button ID="btn_Click" Text="Click" runat="server" />
</asp:PlaceHolder>
</div>
</form>
</body>
</html>

CODEFILE
public partial class dynamicEvent : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click +=new EventHandler(Clicked);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("Button One Clicked");
Button btn = new Button();
plh.Controls.Add(btn);
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("Dynamic Button Clicked");
}
}
[/aspNET:CODE]

Have you tried making sure that the LAST thing you do to the newly created
button, is add it to the Controls collection, rather than adding it and then
setting up the event handler?

-Scott
 
I changed the code. I added the button to the placeholder after I
added the dynamic button click event. Unfortunately, still no
result. Do you have an example of a dynamic button (or control) with
event handler that works?

protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click +=new EventHandler(Clicked);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("HH");
Button btn = new Button();
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
plh.Controls.Add(btn);
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("TT");
}
 
Mr Not So Know It All said:
I changed the code. I added the button to the placeholder after I
added the dynamic button click event. Unfortunately, still no
result. Do you have an example of a dynamic button (or control) with
event handler that works?

protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click +=new EventHandler(Clicked);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("HH");
Button btn = new Button();
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
plh.Controls.Add(btn);
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("TT");
}

Ok. It seems the problem is that you are creating the control at a point
during the page's lifecycle that is too late for it to correctly interact
with the rest of the page.

You should try relocating this code to an earlier stage of the page's
lifecycle, such as Page_Load or LoadViewState.

What this means is that when the first button is clicked, it will cause a
postback and thus a request for a new instance of the page. You could check
for this postback in the Page_Load event and if true, create the new button
along with its event handler.

Here are some good links on this:

http://forums.asp.net/t/1286956.aspx
http://devsushi.com/2006/08/27/aspnet-dynamic-control-creation-part-1/

-Scott
 
I tried this and had success.

protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click += new EventHandler(Clicked);
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
btn.Enabled = false;
btn.Visible = false;
plh.Controls.Add(btn);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("HH");
btn.Enabled = true;
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("TT");
}

is this what you meant?
 
Mr Not So Know It All said:
I tried this and had success.

protected void Page_Load(object sender, EventArgs e)
{
btn_Click.Click += new EventHandler(Clicked);
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
btn.Enabled = false;
btn.Visible = false;
plh.Controls.Add(btn);
}

public void Clicked(object sender, EventArgs e)
{
Response.Write("HH");
btn.Enabled = true;
}

void btn_Click2(object sender, EventArgs e)
{
Response.Write("TT");
}

is this what you meant?

Well, it depends. The way you've got the Page_Load() will always create a
new button, with an event hanlder, dynamically - - every time the page
loads. If you only want the button to be created when your regular button
on the page is clicked, you'd need to check to see "why" the page is loading
before going off and making the new button:

protected void Page_Load(object sender, EventArgs e)
{
if(Page.IsPostBack)
{
btn_Click.Click += new EventHandler(Clicked);
btn.Text = "New Click";
btn.Click += new EventHandler(btn_Click2);
btn.Enabled = false;
btn.Visible = false;
plh.Controls.Add(btn);
}
}

Now, this will only create the dynamic button when the page is being loaded
as a result of the page having already been loaded once and a "Postback"
request was initiated from the prior (non-postback) occurrance of the page.
The first time a page loads, it's not loading as a result of anything being
posted "back" to it, so the first time the page loads, your dynamic button
won't be created.

Of course, we haven't discussed the fact that your page may have several
different controls that can cause a postback and, if that were the case,
then interacting with any of those controls would cause a Postback and
therefore the new button to be created, which may not be what you want. You
might only want the dynamic button to be created when a postback is
initiated from an event of a particular control.

This gets a little trickier, because as a page is being rendered the event
handlers for controls fire AFTER the Page_Load event, which is where you
need to be creating new controls dynamically so that they can become part of
the page properly (as you found out).

So, see if you can follow how the lifecycle of an ASP .NET page would cause
problems:

1. The page is requested for the very first time and its entire lifecycle of
events are processed in order on the server (InitializeComponent,
SaveViewState, Page_Load, Render, Unload, etc.) resluting in the page's
ultimate client code being generated and sent to the client. It's very
important to understand that the page object now falls out of scope and is
no longer accessible. For all intents-and-purposes, that particular
instance of the page class and everything that was stored with it is now
gone! Fortunately, as the page was sending its client code down to the
client, it took a "snapshot" of itself and included it into the code that
was sent down to the client. This "snapshot" is known as "ViewState". So,
the page you recieve basically has instructions on how to build a new page
on the server that is exactly like the one that you now have in your client.

2. When you click a button that was generated by the server (an ASP .NET
button), it causes a postback. The ViewState data is sent (posted) up to
the server and, instead of creating a blank page, the serve recreates a new
instance of a page that looks just like the last one and this new page goes
through its initial events (InitializeComponent, LoadViewState, Page_Load),
but not ALL of th events. After Page_Load, any control event handlers that
you might have created are executed (like button_click events) and after
those, then the page does its final events (Render, unload).

The point here is that most people initially believe that their button_click
event would fire right after they click their button. But, because of the
disconnected nature of HTTP, you can't fire click code on a button that no
longer exists on the server. The server must recreate the page (which
includes your button), in order to react to the button being clicked.

Hope this helps.

-Scott
 
Scott,
Thanks for your tremendous help. I'll read those recommended links. I
appreciate your help.

-DJ
 
Back
Top