Friday, May 30, 2008

Adding fields dynamically in ASP.NET

Adding a control to a page dynamically is a very powerful tool when you want to allow users to add varying amounts of data to their submission. These controls should keep their state through multiple postbacks.

I recently had to solve this problem to allow professors to upload any number of files to our library server using a web form. It seemed simple enough to solve, but as I searched around the net, it seemed many people were having a lot of trouble with this topic or were using some pretty hackish things to get it working. I hope this post helps someone out there.

Using Session

The main problem of adding new controls to a page is that the new controls will disappear whenever there is a new postback. To solve this problem we simply store the control in the users Session which allows them to keep their data as long as their session stays alive.

We can store the controls in a List to keep track of them. When the page is first created, we store the list inside of the Session, then when the page is loaded, we get the list from the Session. Getting the list from the session when the page is loaded guarantees that we have the list of controls for the current user.

Adding Controls Back to Page After Postback

Whenever a postback occurs, all of the controls on a page are recreated. Since a control spawned within the page cycle is not bound to anything, it is simply destroyed.

In order for the dynamically added controls to show up, they must be added at the beginning of each page in the Page_Load method. In this example, we simply iterate through the list and add the control to a placeholder.

Adding a New Control

Whenever a new control is added inside of a button click method, it will not show up on the page immediately. What happens is that it is actually created and added to the array, but the page cycle is already past the Page_Load method, so there is no chance to add the control to the page from the array. To counter this, we simply have to add the control to the page manually inside of the method. In the next postback, the control will be added automatically like the others.

Example Files

Unfortunately, I cannot host files on Blogger so I will copy the contents of the files directly to this post. These files were tested with ASP.Net 3.5 and Visual Studio 2008, but they are simple enough to work on pretty much any platform.

Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Adding Dynamic Controls to a Form</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="myPlaceholder" runat="server"></asp:PlaceHolder>
</div>
<p>
<asp:Button ID="addControl" runat="server" Text="Button"
onclick="addControl_Click" />
</p>
</form>
</body>
</html>


Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
List<Control> controls = new List<Control>();
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
Session["controls"] = controls;
else
controls = (List<Control>)Session["controls"];

/* The controls must be added back to the page each time there
* is a postback, otherwise the controls disappear.*/
foreach (Control control in controls)
myPlaceholder.Controls.Add(control);
}
protected void addControl_Click(object sender, EventArgs e)
{
TextBox box = new TextBox();
box.ID = "box" + controls.Count;
controls.Add(box);

/* We add the box manually first since the Page_Load
method has already finished. The box will only show up
after the next postback otherwise.*/
myPlaceholder.Controls.Add(box);
}
}

7 comments:

Anonymous said...

Thanks!!!!!......Was very Helpful

Anonymous said...

Thanks!! soooo helpful

Ron Rattie said...

I want to add more than one field at a time (5 fields actually) but I don't want them all in a line.. how do I do that?

James Carnley said...

Ron Rattie:

You could add line breaks between them by using the HTML br tag.

The code:
controls.Add(box);

becomes:
controls.Add(box);
controls.Add(new LiteralControl("<br />"));

Also change:
myPlaceholder.Controls.Add(box)

to:
myPlaceholder.Controls.Add(box);
myPlaceholder.Controls.Add(new LiteralControl("<br />"));

Ann Raboschuk said...

Thanks a lot!!!
I've already spent a lot of time to make a dynamic array of controls before)))

Anonymous said...

Thanks i got a good help from this article and i want to know the method to get values from multiple textboxes. Please help

Beyond Kawaii said...

Thanks! This was an incredible amount of help to me.