Reputation: 10777
I have seen a couple of similar questions but none of the solutions worked for me. I have a table and i dinamically add a couple of buttons to it like the following, and i want a single common listener for all buttons:
Button b; //This is defined as a variable in class, not in a function
...
...
void someFunction( . . . )
{
foreach (DataRow row in table.Rows)
{
try
{
string starthour = row["starthour"].ToString(), endhour = row["endhour"].ToString(), day = row["day"].ToString(), building = row["building"].ToString(), room = row["room"].ToString();
int start = Convert.ToInt32(starthour.Substring(0, starthour.Length - 2));
int end = Convert.ToInt32(endhour.Substring(0, endhour.Length - 2));
int startindex = getHourIndex(start);
int endindex = getHourIndex(end);
int dayindex = getDayIndex(day);
for (int i = startindex; i < endindex; i++)
{
b = new Button();
b.Text = subj + numb + " " + section;
Color clr = getCourseColor(subj + numb + section, courses);
b.BackColor = clr;
b.Enabled = true;
b.Click += new EventHandler(button_Click);
table_filter_instructor_schedule.Rows[i].Cells[dayindex].Controls.Add(b);
}
}
catch (Exception)
{
}
}
}
And here is the event handler:
protected void button_Click(object sender, EventArgs e)
{
Response.Redirect("Default.aspx");
}
but the problem is, ebent handler function is never called. Can anyone help me with this*
Thanks
EDIT: Here is how the page looks, and i want to add listener for those buttons:
Upvotes: 0
Views: 806
Reputation: 22456
If you want dynamic controls to work and also raise events, you need to recreate them early in the page lifecycle (Page_Init, Page_Load at the latest). It is important that you assign the same IDs when you recreate the controls and also wire up the event handlers.
Using dynamically created controls usually adds a lot of complexity and you should check whether there is no other way that is simpler. In your function, your buttons are created based on a data table. So it might be a good approach to use a repeater instead of the dynamically created buttons. This allows to wire up events statically.
For a detailed sample on how to create controls dynamically, see this link. However, it also suggests to favor a static approach if possible:
Existing controls can often provide the functionality you get from creating controls dynamically. For example, controls such as the Repeater, DataList, and RadioButtonList controls can dynamically create rows or other control elements when the page runs.
In your specific case (based on your image), I'd propose the following static approach:
The following sample shows the main parts (I've added only columns for three days):
This Repeater creates a very basic HTML table. Please note the buttons in the table rows and the static registration of an event handler.
<asp:Repeater ID="rptTimeTable" runat="server" OnItemDataBound="rptTimeTable_ItemDataBound">
<HeaderTemplate>
<table>
<thead>
<tr>
<td>Time</td>
<td>Mon</td>
<td>Tue</td>
<td>Wed</td>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("Time", "{0:t}") %></td>
<td>
<asp:Button ID="btnMon" runat="server" OnClick="btn_ClickHandler" />
</td>
<td>
<asp:Button ID="btnTue" runat="server" OnClick="btn_ClickHandler" />
</td>
<td>
<asp:Button ID="btnWed" runat="server" OnClick="btn_ClickHandler" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
The data class stores a text for each button that I put on the button later on.
public class RepeaterData
{
public DateTime Time { get; set; }
public string MonText { get; set; }
public string TueText { get; set; }
public string WedText { get; set; }
}
I've placed this in Page_Load (only if it is not a PostBack), but you can run this whenever you like.
var data = new List<RepeaterData>();
data.Add(new RepeaterData() { Time = DateTime.Today.AddHours(9), MonText = "123", TueText = null, WedText = null });
data.Add(new RepeaterData() { Time = DateTime.Today.AddHours(10), MonText = null, TueText = "456", WedText = "789" });
data.Add(new RepeaterData() { Time = DateTime.Today.AddHours(11), MonText = null, TueText = null, WedText = null });
data.Add(new RepeaterData() { Time = DateTime.Today.AddHours(12), MonText = "123", TueText = null, WedText = null });
rptTimeTable.DataSource = data;
rptTimeTable.DataBind();
protected void rptTimeTable_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var data = (RepeaterData)e.Item.DataItem;
SetButtonText(e.Item, "btnMon", data.MonText);
SetButtonText(e.Item, "btnTue", data.TueText);
SetButtonText(e.Item, "btnWed", data.WedText);
}
}
private void SetButtonText(RepeaterItem repeaterItem, string btnId, string btnText)
{
var btn = repeaterItem.FindControl(btnId) as Button;
if (btn != null)
{
if (!string.IsNullOrEmpty(btnText))
btn.Text = btnText;
else
btn.Visible = false;
}
}
protected void btn_ClickHandler(object sender, EventArgs e)
{
// Do whatever you like
}
Upvotes: 1
Reputation: 27944
The problem is that you generate dynamic buttons on your asp page, the ids generated have to be the same over the lifetime of the page. If not the button can not be found at serverside on a postback. The cause can be that you build your table multiple times in the request handling.
Upvotes: 0