Reputation: 5724
I am trying to dynamically build a list of controls inside an updatepanel, and trigger an event from a button on said list of controls.
However, when I click on the control generated, instead of actually firing the trigger, my page does a postback, and never hits the breakpoint I would expect, instead, it only triggers the page load/page init events.
What am I missing?
Default.aspx
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Test._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Button ID="add" Text="add" runat="server" OnClick="add_Click"/>
<asp:updatepanel runat="server" id="test" ChildrenAsTriggers ="false" UpdateMode="Conditional">
<ContentTemplate></ContentTemplate>
</asp:updatepanel>
</asp:Content>
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Test
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void add_Click(object sender, EventArgs e)
{
var container = test.ContentTemplateContainer;
container.Controls.Clear();
Literal literal = new Literal();
literal.Text = DateTime.Now.ToString();
literal.ID = DateTime.Now.Ticks.ToString();
container.Controls.Add(literal);
Button btn = new Button();
btn.Text = "123";
btn.Click += new EventHandler(btnClick);
container.Controls.Add(btn);
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = btn.UniqueID;
trigger.EventName = "Click";
test.Triggers.Add(trigger);
}
protected void btnClick(object sender, EventArgs e) {
System.Diagnostics.Debugger.Break(); //never gets hit
var abc = 16;
}
}
}
Upvotes: 1
Views: 410
Reputation: 35514
The button never hits btnClick
because the button does not exist. You are creating the buttton on a button click event, but it is lost on PostBack.
Dynamicly added controls must always be added again for every PostBack action in the Page_Load event handler or they will dissapear from the page. But because you are using an UpdatePanel it still looks that they are present.
Try this below and you will see that this time the button click does work.
protected void Page_Load(object sender, EventArgs e)
{
var container = testje.ContentTemplateContainer;
container.Controls.Clear();
Button btn = new Button();
btn.Text = "123";
btn.Click += new EventHandler(btnClick);
container.Controls.Add(btn);
}
If you want to add more than one set of Literals and Buttons with add_Click
you need to store the number of clicks in a ViewState
and create a function that loops the count in the ViewState when the page is reloaded.
Here an example of how it should work.
//declare global integer
int controlCount = 0;
protected void Page_Load(object sender, EventArgs e)
{
//check if the viewstate exists
if (ViewState["controlCount"] != null)
{
try
{
//convert viewstate to int
controlCount = Convert.ToInt32(ViewState["controlCount"]);
}
catch
{
}
}
//call the funcion to add the controls on every page load
addControls();
}
protected void add_Click(object sender, EventArgs e)
{
//pretty obvious what this does...
controlCount++;
addControls();
}
private void addControls()
{
var container = testje.ContentTemplateContainer;
container.Controls.Clear();
//loop the currect control count
for (int i = 0; i < controlCount; i++)
{
Literal literal = new Literal();
literal.Text = "Literal " + i;
literal.ID = "myLiteral_" + i;
container.Controls.Add(literal);
Button btn = new Button();
btn.Text = "Button " + i;
btn.ID = "myButton_" + i;
btn.Click += new EventHandler(btnClick);
container.Controls.Add(btn);
}
//set the viewstate again with the new control count
ViewState["controlCount"] = controlCount;
}
protected void btnClick(object sender, EventArgs e)
{
//cast the sender as a button
Button btn = sender as Button;
//split the ID to get the count
string [] btnNr = btn.ID.Split('_');
//find the literal that goes with the clicked button
Literal literal = testje.FindControl("myLiteral_" + btnNr[1]) as Literal;
//alert the literal text
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "doPopup", "alert('" + literal.Text + "')", true);
}
Upvotes: 2