Reputation: 121
I'm brand-new to ASP.NET, so bear with me.
Here's a simplified explanation of my scenario. I have a button on a page. When I click the button, I'm retrieving a list of strings from a database and dynamically generating a series of link buttons with the retrieved strings as the Text of the link buttons.
I already understand that I can't do this in the button's click event handler for several reasons. I also understand that dynamic controls need to be generated in the Page_Init or Page_Load event handlers so that the link buttons' click events can be wired up.
So, here's the process I considered:
Here's the problem: because of the page's life cycle, the button's click event isn't dealt with until AFTER the Page_Load event. As such, the strings I use to generate the link buttons aren't retrieved and assigned to the ViewState variable until AFTER the Page_Load event (where I was hoping to create the link buttons).
As such, the link buttons aren't generated until the SECOND click of the button, when the ViewState variable has been assigned. Obviously, this is a problem.
The solution I devised works, but I don't know if it's the optimal solution. Here's the method I'm using:
Now, this solution actually works. However, if I refresh the page, I get the Confirm Form Resubmission pop-up (which I don't like, but I can live with).
My question to the pro-coders on here is -- how would you have handled my situation?
UPDATE:
Here's a solution that seems to work. I may have been confused about where event handlers can be wired up, but please take a look at this code and tell me if it makes sense or if it's just a hack:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if(ViewState["ControlsArray"] != null)
{
ArrayList controlsList = (ArrayList)ViewState["ControlsArray"];
GenerateLinkButtons(controlsList);
}
}
}
//The event handler for the dynamically generated linkbuttons
void linkButton_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
string btnName = btn.Text;
Response.Write(btnName);
}
//The click event handler for the Generate Controls button
protected void Button1_Click(object sender, EventArgs e)
{
ArrayList PageArrayList = new ArrayList();
PageArrayList = new ArrayList();
PageArrayList.Add("Text 1");
PageArrayList.Add("Text 2");
PageArrayList.Add("Text 3");
PageArrayList.Add("Text 4");
PageArrayList.Add("Text 5");
GenerateLinkButtons(PageArrayList);
ViewState["ControlsArray"] = PageArrayList;
}
void GenerateLinkButtons(ArrayList controlsList)
{
int i = 1;
foreach (string s in controlsList)
{
LinkButton lnkButton = new LinkButton();
lnkButton.ID = "btn" + i;
lnkButton.Text = s;
this.form1.Controls.Add(lnkButton);
this.form1.Controls.Add(new LiteralControl("<br />"));
lnkButton.Click += new EventHandler(linkButton_Click);
i++;
}
}
}
Upvotes: 3
Views: 1543
Reputation: 4903
dynamic controls need to be generated in the Page_Init or Page_Load event handlers so that the link buttons' click events can be wired up.
Actually, You can create controls on the Button Click event. But you have to make sure these controls are recreated in the following PostBacks.
So let's say you have a property called Data
that points to a ViewState variable. Let's also assume that you are using a Repeater
to create the LinkButtons.
Then you could do something like this:
private List<string> Data
{
get { return (List<string>)ViewState["Data"]; }
set { ViewState["Data"] = value; }
}
protected void Button_Click(object sender, EventArgs e)
{
Data = GetData();
LoadRepeater();
}
protected void Page_Load(object sender, EventArgs e)
{
if(Data != null)
{
LoadRepeater();
}
}
private void LoadRepeater()
{
repeater.DataSource = Data;
repeater.DataBind();
}
Repeater:
<asp:Repeater id="repeater" runat="server">
<ItemTemplate>
<asp:LinkButton id="link" runat="server" OnClick="link_Click" />
</ItemTemplate>
</asp:Repeater>
protected void link_Click(object sender, EventArgs e)
{
//Do Stuff
}
Additionally, if you want to avoid the Confirm Form Resubmission
, use the ASP.NET UpdatePanel
control.
Example:
<asp:UpdatePanel id="upp" runat="server" >
<ContentTemplate>
<!-- Button-->
<!-- Repeater-->
<!-- Other Stuff-->
</ContentTemplate>
</asp:UpdatePanel>
Another approach (not sure if it works):
Try setting the repeater DataSource on the Tag Definition:
<asp:Repeater id="repeater" runat="server" DataSource='<%# Data %>' >
<ItemTemplate>
<asp:LinkButton id="link" runat="server" OnClick="link_Click" />
</ItemTemplate>
</asp:Repeater>
protected void Button_Click(object sender, EventArgs e)
{
Data = GetData();
LoadRepeater();
}
protected void Page_Load(object sender, EventArgs e)
{
}
private void LoadRepeater()
{
repeater.DataBind();
}
Upvotes: 2