VWD/C#/aspx: event handler doesn't trigger

Associate
Joined
9 Dec 2008
Posts
387
Code:
.
.
.
                Button bt = new Button();
                bt.Text = "Click Me";
                bt.Click += new EventHandler(bt_Click);
.
.
.
    void bt_Click(object sender, EventArgs e)
    {
        lbl1.Text = "Hello";    
    }
Using Visual Web Developer. It's a webforms page. Above shows how in a procedure I'm dynamically creating a button and then binding an event handler to it. Clicking the button just reloads the page and doesn't perform the action in the event handler. :confused:
 
rebind lbl1.
Thanks for reply. Um, lbl1 is not dynamic. It's created in the non-code file:
Code:
<asp:Label id="lbl1" text="No text yet" runat="server" />

edit: in other words, the lbl1.Text property is accepting and displaying-on-page string values that are dynamically set to it via other events (that's confirmed). So the button event handler is not firing.
 
Last edited:
Can you post the entire code file please? Impossible to see what's going on without the full picture of the context.
Ok here goes. Why I'm creating a button inside a dynamically created table is beyond scope, but that's the context. Here's the code portion:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
public void MakeTable(object sender, EventArgs e)
    {
            HtmlTableRow rownp = new HtmlTableRow();
            HtmlTableCell cellnp = new HtmlTableCell();
            //THE DYNAMIC BUTTON IS HERE **************************************
            Button bt = new Button();
            bt.Text = "Click Me";
            bt.Click += new EventHandler(bt_Click);
            cellnp.Controls.Add(bt);
            rownp.Controls.Add(cellnp);
            TheTable.Rows.Add(rownp);
    }

protected void Page_Load(object sender, EventArgs e)
    {
    }

    void bt_Click(object sender, EventArgs e)
    {
        lbl1.Text = "Hello";
    }
}

And the non-code portion. The static "lbl1" label is created in here. A staticaly created button triggers the MakeTable procedure above which contains the dynamic button "bt" and it's event assignment which will make "lbl1" say "hello" ... obviously that's not what the intended website will do... I'm testing the idea of dynamically created buttons in a dynamic table.
Code:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Button ID="btMakeTable" Text="Make Table" OnClick="MakeTable" runat="server" />
<asp:Label ID="lbl1" Text="No text yet" runat="server" />
<table id="TheTable" border="0" cellpadding="0" cellspacing="0" runat="server" />
</asp:Content>

Cheers
 
Last edited:
You still need to bind it because you are dynamically adding components to it.
Ok. Bind it to what? (sorry never b4 made dynamicly created controls before) Constructing the table works and displays everything including the buttons (no compilation errors). But without binding it, controls within it cannot trigger events?

Cheers
 
no you dont have to databind the label

If he puts lbl1.Text = "some text"; into Page_Load it will work...

Stelly
Yeah I know that. I want the text to change inside the event handler of the dynamically created button to show that it's event is triggering.

Ok another way of interpreting what you say is set the "value" in a staticly declared HiddenField to "Hello" (in the button's event) and then assign that value to lbl1.Text in the Page_Load. But that didn't work. The event just doesn't trigger.

Also databind made no difference.
Code:
public void MakeTable(object sender, EventArgs e)
    {            
            TableRow rownp = new TableRow();
            TableCell cellnp = new TableCell();
            Button bt = new Button();
            bt.Text = "Click Me";
            bt.Click += new EventHandler(bt_Click);
            cellnp.Controls.Add(bt);
            rownp.Controls.Add(cellnp);
            TheTable.Rows.Add(rownp);
            TheTable.DataBind();  //**********************
            
    }

void bt_Click(object sender, EventArgs e)
    {
        lbl1.Text = "Hello";
        lbl1.DataBind();       //**********************
    }
 
Last edited:
trying to do MVC and this at the same time is not helping :)

I personally think that when its posting back its losing the controls in the viewstate.

Stelly
The viewstate should be retained by default.

edit: I just explicitly set the EnableViewState property of the static Label object "lbl1" to true. Still shows that the button's event not trigging. I wonder what property still needs to be set to make this button functional...
Code:
            HtmlTableRow rownp = new HtmlTableRow();
            HtmlTableCell cellnp = new HtmlTableCell();
               Button bt = new Button();
               bt.Text = "Click Me";
               bt.Click += new EventHandler(bt_Click);
            cellnp.Controls.Add(bt);
            rownp.Controls.Add(cellnp);
            TheTable.Rows.Add(rownp);
 
Last edited:
I have a theory. I think the Button "bt" control needs to be added with the ".Add" method to the asp object "BodyContent". I just don't know how to do that. I don't know how to access the object BodyContent and its ".Controls.Add" method...
Code:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
That's what contains the other static controls.

p.s. I keep hitting ctrl-s after editing my posts... :)
 
Same time?! :p

DataBinding controls registers them in the view state. The ASP life cycle is annoying as hell, and you need to databind your controls for every cycle - thus my suggestion to try binding the label in the event :p
Is not DataBind() related to the DataSource property tho? So by itself it does nothing, no?
Code:
   rb.DataSource=myList;
   rb.DataBind();
that's binding a radiobuttonlist to a list of elements.
 
try adding the button to a place holder.

Stelly
Yeah the "BodyContent" object is a place holder. I've seen an example of adding content to a place holder ... was trying to find it just now. But I think the statically declared <table ... runat="server" /> is essentially a place holder too is it not?

My brain is starting to hurt.
 
Its definately the viewstate causing you issue, you are losing it on postback which is a complete pain!

Stelly
I just tried adding the button to the following place holder (which itself worked), but the event still didn't trigger.
Code:
<asp:PlaceHolder ID="h" runat="server"></asp:PlaceHolder>
As for the viewstate, I think the default is to prserve it, but below is the Label object declaration with viewstate explicity set to true, but still doesn't show the text change that should be resulting from the event handler...
Code:
<asp:Label ID="lbl1" EnableViewState="true" Text="No text yet" runat="server" />
 
Anyway, it can't be the viewstate of the label, because a statically declared button does trigger the event and the text changes.
Code:
<asp:Button ID="btStatic" Text="Static" OnClick="bt_Click" runat="server" />
So there must be just some property missing from how the button "bt" is being dynamically created.
 
I just read that you cannot use the event handlers of dynamically created buttons.

There are apparently some ciruitous work arounds to it which I'm currently trying to decipher... hmmm...
 
You can use the event handlers of dynamically created buttons; however they're a pain to get right. Here are common causes of this problem:

Not enough of the control tree (nested Controls collections) exists for the viewstate to load properly, or the control tree that exists on the POST request is different from the control tree that exists on the original GET request.

Or you the control tree is being (re)created too late in the page lifecycle for the event to fire on post.

We need to see the whole code behind page to diagnose this one.

akakjs
Thanks for help. The "whole code" regarding this is literally just the brief test code in order to see if it will work. I have not incorporated this into any project yet.

The button is successfully created as a part of a table cell and reloads the page upon clicking but does not trigger the event in which the text for a ViewState-preserved Label gets set to "hello". Here's a quote of my post where I included the test code.

Ok here goes. Why I'm creating a button inside a dynamically created table is beyond scope, but that's the context. Here's the code portion:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
public void MakeTable(object sender, EventArgs e)
    {
            HtmlTableRow rownp = new HtmlTableRow();
            HtmlTableCell cellnp = new HtmlTableCell();
            //THE DYNAMIC BUTTON IS HERE **************************************
            Button bt = new Button();
            bt.Text = "Click Me";
            bt.Click += new EventHandler(bt_Click);
            cellnp.Controls.Add(bt);
            rownp.Controls.Add(cellnp);
            TheTable.Rows.Add(rownp);
    }

protected void Page_Load(object sender, EventArgs e)
    {
    }

    void bt_Click(object sender, EventArgs e)
    {
        lbl1.Text = "Hello";
    }
}

And the non-code portion. The static "lbl1" label is created in here. A staticaly created button triggers the MakeTable procedure above which contains the dynamic button "bt" and it's event assignment which will make "lbl1" say "hello" ... obviously that's not what the intended website will do... I'm testing the idea of dynamically created buttons in a dynamic table.
Code:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Button ID="btMakeTable" Text="Make Table" OnClick="MakeTable" runat="server" />
<asp:Label ID="lbl1" Text="No text yet" runat="server" />
<table id="TheTable" border="0" cellpadding="0" cellspacing="0" runat="server" />
</asp:Content>

Cheers
 
Well I found one imperfect but simple solution. I realized that the Button has a PostBackUrl property. Normally that simply contains just "PageName.aspx". So you just change the property text to like "PageName.aspx?Action=5". The button triggers a postback by default (without triggering a specific event handler) and then you catch the param on-postback. Not perfect but I can adjust the code to it.

Cheers
 
Hi guys,
Thanks for input. Since posting my own solution above, I've gone with that solution and it's been working fine. As part of the work around I had to make sure that all static buttons (which trigger normal event handlers) have their postbackurl property statically set to include the page url without params so that the params created by the dynamic buttons do not persist throughout the session. It's doable and works fine, but something where the dynamic buttons don't need to use url params is better.

When I have some time in the next few days, I'll take a look at and try the solutions from BlackCoat and Eriedor.

Eriedor:
When I was trying this out, I did also have a version where the table and dynamic buttons were being rebuilt upon postback, but it wasn't working (event handler wasn't being triggered). I'll take a look at your specific solution though.

Cheers
 
Like I mentioned above I will be trying the suggested solutions soon, but I just wanted to add a point about a problem with shared webhosting that causes the event handler problem discussed here even for static buttons.

On the shared server, the application pool gets recycled as often as every 10 minutes. When that happens, the session states of all web pages that haven't been interacted-with within the past few minutes get cleared. At the minimum, that means that one has to rely on either database or cookies to store any session state info.

An additional problem caused by the above is that when the application pool gets recycled all buttons including static buttons lose their association to event handlers. A simple way to deal with that is the same as the solution that I have used for dynamic buttons, but in a slightly more minimal "backup" fashion. I still associate events with the static buttons (because it's more efficient and organized)... url params are ignored unless the page script detects that the session state has cleared too early.

SO, while I will be trying out these solutions, it may end up being needlessly complicated for the dynamic buttons, because ultimately the dynamic buttons need a backup system just like the static buttons do because of application pool recycling.

Cheers
 
Back
Top Bottom