In my previous post here, I wrote an example that demonstrates how are we going to generate table rows dynamically using ASP Table on click of the Button control. Now based on some comments in my previous example and in the forums they wanted to implement it within Masterpage. Unfortunately the code in my previous example doesn't work in Masterpage for the following main reasons: The Table is dynamically added within the Form tag and so the TextBox control will not be generated correcty in the page. The data will not be retained on each and every postbacks because the SetPreviousData() method is looking for the Table element within the Page and not on the MasterPage. The Request.Form key value should be set correctly since all controls within the master page are prefixed with the naming containter ID to prevent duplicate ids on the final rendered HTML. For example the TextBox control with the ID of TextBoxRow will turn to ID to this ctl00$MainBody$TextBoxRow. In order for the previous example to work within Masterpage then we will have to correct those three main reasons above and this post will guide you how to correct it. Suppose we have this content page declaration below: <asp:Content ID="Content1" ContentPlaceHolderID="MainHead" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainBody" Runat="Server">
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
<asp:Button ID="BTNAdd" runat="server" Text="Add New Row" OnClick="BTNAdd_Click" />
</asp:PlaceHolder>
</asp:Content>
As you notice I've added a PlaceHolder control within the MainBody ContentPlaceHolder. This is because we are going to generate the Table in the PlaceHolder instead of generating it within the Form element. Now since issue #1 is already corrected then let's proceed to the code beind part. Here are the full code blocks below:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class DynamicControlDemo : System.Web.UI.Page
{
private int numOfRows = 1;
protected void Page_Load(object sender, EventArgs e) {
//Generate the Rows on Initial Load
if (!Page.IsPostBack) {
GenerateTable(numOfRows);
}
}
protected void BTNAdd_Click(object sender, EventArgs e) {
if (ViewState["RowsCount"] != null) {
numOfRows = Convert.ToInt32(ViewState["RowsCount"].ToString());
GenerateTable(numOfRows);
}
}
private void SetPreviousData(int rowsCount, int colsCount) {
Table table = (Table)this.Page.Master.FindControl("MainBody").FindControl("Table1"); // **** if (table != null) {
for (int i = 0; i < rowsCount; i++) {
for (int j = 0; j < colsCount; j++) {
//Extracting the Dynamic Controls from the Table
TextBox tb = (TextBox)table.Rows[i].Cells[j].FindControl("TextBoxRow_" + i + "Col_" + j);
//Use Request object for getting the previous data of the dynamic textbox
tb.Text = Request.Form["ctl00$MainBody$TextBoxRow_" + i + "Col_" + j];//***** }
}
}
}
private void GenerateTable(int rowsCount) {
//Creat the Table and Add it to the Page
Table table = new Table();
table.ID = "Table1";
PlaceHolder1.Controls.Add(table);//****** //The number of Columns to be generated
const int colsCount = 3;//You can changed the value of 3 based on you requirements
// Now iterate through the table and add your controls
for (int i = 0; i < rowsCount; i++) {
TableRow row = new TableRow();
for (int j = 0; j < colsCount; j++) {
TableCell cell = new TableCell();
TextBox tb = new TextBox();
// Set a unique ID for each TextBox added
tb.ID = "TextBoxRow_" + i + "Col_" + j;
// Add the control to the TableCell
cell.Controls.Add(tb);
// Add the TableCell to the TableRow
row.Cells.Add(cell);
}
// And finally, add the TableRow to the Table
table.Rows.Add(row);
}
//Set Previous Data on PostBacks
SetPreviousData(rowsCount, colsCount);
//Sore the current Rows Count in ViewState
rowsCount++;
ViewState["RowsCount"] = rowsCount;
}
}
As you observed the code is pretty much similar to the previous example except for the highlighted lines above.
That's it! I hope someone find this post usefu!
Technorati Tags: Dynamic Controls,ASP.NET,C#,Master Page