How to Dynamically Create ASP.NET Controls Within Dynamically Created ASP.NET Controls

How to dynamically create ASP.net controls within dynamically created ASP.net controls

Here is an example for continuously adding buttons to the page. Every newly created button can also add another button to the page. This can be used with all types of Controls.
Also you will have to recreate dynamic controls on every PostBack, otherwise they and their contents will be lost.

protected void Page_Load(object sender, EventArgs e)
{
//set the initial number of buttons
int buttonCount = 1;

//check if the viewstate with the buttoncount already exists (= postback)
if (ViewState["buttonCount"] != null)
{
//convert the viewstate back to an integer
buttonCount = Convert.ToInt32(ViewState["buttonCount"]);
}
else
{
ViewState["buttonCount"] = buttonCount;
}

//create the required number of buttons
for (int i = 1; i <= buttonCount; i++)
{
createButton(i);
}
}

private void createButton(int cnt)
{
//create a new button control
Button button = new Button();
button.Text = "Add another Button (" + cnt + ")";

//add the correct method to the button
button.Click += DynamicButton_Click;

//another control, in this case a literal
Literal literal = new Literal();
literal.Text = "<br>";

//add the button and literal to the placeholder
PlaceHolder1.Controls.Add(button);
PlaceHolder1.Controls.Add(literal);
}

protected void DynamicButton_Click(object sender, EventArgs e)
{
//get the current number of buttons
int buttonCount = Convert.ToInt32(ViewState["buttonCount"]) + 1;

//create another button
createButton(buttonCount);

//set the new button count into the viewstate
ViewState["buttonCount"] = buttonCount;
}

UPDATE

You can also delegate a Command to a button instead of a Click, and with this you can send a variable along with the button as a CommandArgument. You will have to change the creation of the button a bit.

//add the correct method to the button
button.Command += DynamicButton_Command;

//now you can also add an argument to the button
button.CommandArgument = "Create Hazard";

You will also need a different method to handle the button clicks.

protected void DynamicButton_Command(object sender, CommandEventArgs e)
{
//get the current number of buttons
int buttonCount = Convert.ToInt32(ViewState["buttonCount"]) + 1;

//create another button
createButton(buttonCount);

//set the new button count into the viewstate
ViewState["buttonCount"] = buttonCount;

//get the commandargument from the button
string buttonArgument = e.CommandArgument.ToString();
}

How to dynamically create controls in asp.net aspx file

In WebForms, you can make use of listing controls that have a concept of a DataSource (Some listing of objects) and a template which renders how each of those objects appear. In general, you should use these whenever you have a list of items that you want to render on the site.

In this particular case, you will probably want to make use of the ListView control. This allows you to define a layout template and an item template.

Your aspx markup would look like the following:

<asp:ListView ID="lvCpus" OnItemDataBound="lvCpus_ItemDataBound" runat="server">
<LayoutTemplate>
<div class="row product cpu">
<div runat="server" id="itemPlaceholder"></div>
</div>
</LayoutTemplate>
<ItemTemplate>
<div runat="server" class="col-md-3">
<img class="center-block" src="Content/images/processor.jpg" />
<span class="price"><%# Eval("Price") %></span>
<span class="addtocart">
<asp:Button ID="addToCart" Text="Add To Cart" runat="server" />
</span>
</div>
</ItemTemplate>
</asp:ListView>

This defines a ListView control and creates a LayoutTemplate that matches your container. Internally it has a div that must have the id itemPlaceholder which is used to populate the various items that are bound to this control.

The ItemTemplate portion defines what you expect each individual item to look like. In this case, it's a column that contains a CPU for purchase.

Notice that the button is defined as a regular ASP Web Control, but none of the dynamic data is set. That's because if you try to assign a property like CommandArgument with an evaluated item, the server tag will not be well-formed and you'll get the YSOD. To work around this, you need to specify an OnItemDataBound function for the ListView that is called when you bind data to this Web Control. In my case, it's called lvCpus_ItemDataBound.

The ItemDataBound method in this case will look like the following:

protected void lvCpus_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
var cpu = e.Item.DataItem as Cpu;

if (cpu == null)
{
return;
}

var btn = e.Item.FindControl("addToCart") as Button;

if (btn == null)
{
return;
}

btn.CommandArgument = cpu.Id.ToString();
// Set other server-side properties required from code.
}
}

When you bind a data source, it has 0 or more items in it. For every item in the data source, this method is called and will let you specify server-side appropriate values that can't be expressed directly in the template.

In our case, we specify the CommandArgument from the Cpu class, but other values could be specified as well.

Finally, we need to make sure we can fill the list view with data. So in Page_Load perhaps, we can bind data to this ListView like the following:

protected void Page_Load(object sender, EventArgs e)
{
lvCpus.DataSource = GetCpus();
lvCpus.DataBind();
}

private IEnumerable<Cpu> GetCpus()
{
yield return new Cpu { Id = 1, Price = 5 };
yield return new Cpu { Id = 2, Price = 10 };
yield return new Cpu { Id = 3, Price = 15 };
yield return new Cpu { Id = 4, Price = 15 };
yield return new Cpu { Id = 5, Price = 20 };
}

We first set the List View's data source to the CPU list that you have and then call the DataBind() method on the ListView. This triggers the OnItemDataBound function to begin filling in the data, and at the end you are left with, in this case, 5 CPUs displayed on the site.

ASP.NET dynamically created controls and Postback

For anyone else trying to do something like this: don't. Instead, think of the flow of information and understand that there is a better way to do it. The input control(s) do not need to be dynamically created. They can be static, and upon filling out and submitting on one, that information has to go somewhere (database, cache, session, for example). Once its there, on postback, loop through all items in your storage of choice and create a display for them.

That is what I've done and it has made life a lot easier. Hope it helps someone.

Retain Dynamic Controls in asp.net

Dynamic controls are lost after postback. You have to re-created them after each post-back. you will have to make use of View-State

protected int NumberOfControls
{
get{return (int)ViewState["NumControls"];}
set{ViewState["NumControls"] = value;}
}


private void addSomeControl()
{
TextBox tx = new TextBox();
tx.ID = "ControlID_" + NumberOfControls.ToString();
Page.Controls.Add(tx);
this.NumberOfControls++;
}

Please visit the following Urls:

ASP.Net Dynamic Controls ViewState: Retain state for dynamically created controls on PostBack

Retaining State for Dynamically Created Controls in ASP.NET applications

ViewState in Dynamic Control

How to access dynamically created server controls in asp.net

To test your scenario, i added 2 controls txtOutput and Getvalues button.Everything seems to be fine, except your control ids starts from 0 where as your for loop starts from 1.

However this should not return null in FindControl.

I suspect your table id is incorrect because in the other post you referred the table id is "tbl".

Other wise everything seems to be correct. Anyway, i have pasted your code which i tried here, and it works.

Another possibility where you will get the error is if u try to access the controls before even they are created in Page_Load. However because you have 2 rows static in your table, your code should work irrespective of the dynamic control creation. Pls try the below code and update

<form id="form1" runat="server">
<div>
<div>
<asp:Table ID="tbl" runat="server">
<asp:TableRow ID="rw0">
<asp:TableCell ID="c01" Width="100px">
<asp:CheckBox runat="server" ID="chk0" />
</asp:TableCell>
<asp:TableCell ID="c02" Width="100px">
<asp:TextBox runat="server" ID="txt0" />
</asp:TableCell></asp:TableRow>
<asp:TableRow ID="rw1">
<asp:TableCell ID="c11" Width="100px">
<asp:CheckBox ID="chk1" runat="server" />
</asp:TableCell><asp:TableCell ID="c12" Width="100px">
<asp:TextBox runat="server" ID="txt1" />
</asp:TableCell></asp:TableRow>
</asp:Table>
<asp:textbox runat="server" id="checkIn" ClientIDMode="Static" name="checkIn" ></asp:textbox>
<asp:Button ID="btn1" runat="server" Text="Add Row" OnClick="addRow" />
<br />
<asp:Button ID="GetValues" runat="server" Text="GetValues" OnClick="GetValuesfromDynamicControls" />
<asp:TextBox ID="txtOutput" runat="server" />

//code behind starts here

 public partial class DynamicControl : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

if (IsPostBack)
{
int num_row = (int)Session["No_of_Rows"];
for (int i = 2; i < num_row; i++)
{
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TextBox tb = new TextBox();
CheckBox cb = new CheckBox();

row.ID = "rw" + i;

cell1.ID = "c" + i + "1";
cell2.ID = "c" + i + "2";

tb.ID = "txt" + i;
tb.EnableViewState = true;
cb.ID = "chk" + i;

cell1.Controls.Add(cb);
cell2.Controls.Add(tb);

row.Cells.Add(cell1);
row.Cells.Add(cell2);

tbl.Rows.Add(row);
}
}
else
{
Session["No_of_Rows"] = 2;
}
}

protected void addRow(object sender, EventArgs e)
{
int num_row = (int)Session["No_of_Rows"];
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TextBox tb = new TextBox();
CheckBox cb = new CheckBox();

row.ID = "rw" + num_row;

cell1.ID = "c" + num_row + "1";
cell2.ID = "c" + num_row + "2";

tb.ID = "txt" + num_row;
tb.EnableViewState = true;
cb.ID = "chk" + num_row;

cell1.Controls.Add(cb);
cell2.Controls.Add(tb);

row.Cells.Add(cell1);
row.Cells.Add(cell2);

tbl.Rows.Add(row);
Session["No_of_Rows"] = tbl.Rows.Count;
}


protected void GetValuesfromDynamicControls(object sender, EventArgs e)
{
//int rows =Convert.ToInt32( Session["No_of_Rows"]);
int rows = Convert.ToInt32(tbl.Rows.Count);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rows; i++)
{
TextBox tb =(TextBox) Page.FindControl("txt" + i);
sb.Append(tb.Text + ";");
}

txtOutput.Text = sb.ToString();
}

}

fill dynamically created controls in asp.net.

Asp.net needs to know what controls are there on a page. It is non trivial to add elements in javascript and receive the data later into controls at the backend.

The correct way to do this is to add the controls at server side into the controls collection.

Refer: How to: Add Controls to an ASP.NET Web Page Programmatically

Label myLabel = new Label();
myLabel.ID = "myLabel";
myLabel.Text = "Sample Label";
Panel1.Controls.Add(myLabel);

When controls are added to the controls collection via someContainer.Controls.Add you can then find them using someContainer.FindControl

Label myLabel = (Label)someContainer.FindControl("myLabel");

You also need to be completely aware of the asp.net page life cycle, if you don't want any surprises when adding controls dynamically.



Related Topics



Leave a reply



Submit