Actually i'm creating web template using asp.net and c#.
in my user control page i have to create the table dynamically. i just read the data from XML file then retrieve the name and number of columns and rows of each table. while i'm creating the table i assign the name and id to each cell. because i have one row including some textbox for adding the data to database. but after i have created the table i can not access to the textbox cells based on id to get their data and insert it to database. my dynamic table code is:

public void CreateAddDynamicTable()
{
    XmlDocument xDocRead = new XmlDocument();
    xDocRead.Load(Server.MapPath("ModuleTemp.xml"));
    string xModuleName = hid_ChooseModule.Value;
    XmlNode xColCounter = xDocRead.SelectSingleNode("ModuleTemp/" + xModuleName + "/List");
    int colCount = xColCounter.ChildNodes.Count;

    int nonPkCounter = 0;
    string[] nonPrimaryKey = new string[100];
    string[] nonPkNewDataTemp = new string[100];

    for (int i = 1; i <= colCount; i++)
    {
        if (xDocRead.SelectSingleNode("ModuleTemp/" + xModuleName + "/Add/TableColumn" + i).Attributes.GetNamedItem("IsPrimaryKey").Value == "N")
        {
            nonPrimaryKey[nonPkCounter] = xDocRead.SelectSingleNode("ModuleTemp/" + xModuleName + "/Add/TableColumn" + i).Attributes.GetNamedItem("Name").Value;
            nonPkCounter++;
        }
    }

    ph_Uc_AddModule.Controls.Clear();

    // Fetch the number of Rows and Columns for the table 
    // using the properties
    int tblRows = nonPkCounter;
    int tblCols = 2;

    // Create a Table and set its properties 
    Table tbl = new Table();
    // Add the table to the placeholder control
    ph_Uc_AddModule.Controls.Add(tbl);
    // Now iterate through the table and add your controls 
    for (int i = 0; i < tblRows; i++)
    {
        TableRow tr = new TableRow();
        for (int j = 0; j < tblCols; j++)
        {
            TableCell tc = new TableCell();
            Label td_Add_Header = new Label();
            TextBox td_Add = new TextBox();

            if (j == 0)
            {
                td_Add_Header.Text = nonPrimaryKey[i];
                td_Add_Header.ID = "lb" + (i + 1) + "_header_AddModule";

                // Add the control to the TableCell
                tc.Controls.Add(td_Add_Header);
                tc.CssClass = "td_Header_AddModule";
            }
            else
            {
                td_Add.Text = "";
                td_Add.ID = "tb" + (i + 1) + "_AddModule";
                // Add the control to the TableCell
                tc.Controls.Add(td_Add);
                tc.CssClass = "td_Tb_AddModule";
            }

            // Add the TableCell to the TableRow
            tr.Cells.Add(tc);
        }
        // Add the TableRow to the Table
        tbl.Rows.Add(tr);
    }
}

my user control page which is contain a PlaceHolder is as below:

<asp:Panel ID="pn_Uc_TModule" runat="server">

<asp:Table runat="server" ID="table_Uc_TModule" CssClass="table_Uc_TModule" Width="100%">
 <asp:TableRow runat="server" VerticalAlign="Top" Height="50px">
                <asp:TableCell runat="server">
                    <asp:Button runat="server" Text="" CssClass="btn_Add_Active" OnClick="btn_AddNew_Click" />
                    <asp:Button ID="btn_Cancel_NewItem" runat="server" Text="" CssClass="btn_Cancel_New" OnClick="btn_Cancel_AddNew" Visible="false" />

                    <asp:Table runat="server" ID="table_Uc_AddModule" Visible="false">
                        <asp:TableRow runat="server">
                            <asp:TableCell runat="server" >

                                <asp:PlaceHolder ID="ph_Uc_AddModule" runat="server">
                                </asp:PlaceHolder>

                            </asp:TableCell>
                        </asp:TableRow>
                        <asp:TableRow ID="TableRow1" runat="server">
                            <asp:TableCell runat="server" CssClass="td_Tb_AddModule" HorizontalAlign="Center">
                                <asp:Button ID="btn_Insert" runat="server" OnClick="Uc_AddModule_ItemInsert" Text="" CssClass="btn_Add" />
                                <asp:Button ID="btn_Cancel" runat="server" OnClick="Uc_AddModule_Clear" Text="" CssClass="btn_Clear" />
                            </asp:TableCell>
                        </asp:TableRow>
                    </asp:Table>

                </asp:TableCell>
            </asp:TableRow>
</asp:Table>
</asp:Panel>

i'm using below method in my insert function at the code behind to access the data inserted at the textbox:

for (int i = 1; i <= nonPkCounter; i++)
    {
        TextBox textBox = (ph_Uc_AddModule.FindControl("tb" + i + "_AddModule")) as TextBox;
        nonPkNewDataTemp[i] = textBox.Text;
    }

i have tried pn_Uc_TModule.FindControl("tb" + i + "_AddModule") and also _Uc_AddModule.FindControl("tb" + i + "_AddModule") but still con not get the texbox data to insert it to database. could you please guide me how to get it done.
appreciate your consideration.

Dani AI

Generated

— two problems are happening at once. First, calling FindControl on the placeholder will not find TextBoxes nested inside a Table/Row/Cell because FindControl only looks at direct children. Second, dynamically created controls must be recreated on every postback at the correct point in the page lifecycle so ASP.NET can populate their posted values; if you only build the table on the initial request the TextBox controls do not exist on postback and you get nulls. 's suggestion (public properties) is fine for fixed, known controls, but with a variable number of columns you need to recreate the controls instead.

What to do (practical steps):

  • Persist the metadata that defines the dynamic UI (the list of non-PK column names and a flag that the add-panel is visible). Use ControlState or Session, or re-read the same XML based on a module identifier you can read from Request.Form.
  • Rebuild the table on every request before post data is processed — e.g., in the user control's OnInit (or Page_Init) call your CreateAddDynamicTable so controls exist in time for ASP.NET to load posted values. Make the TextBox IDs stable and deterministic so mapping works.
  • When reading values, either iterate the Table.Rows/TableCells to pick the TextBox in each cell or use a small recursive finder to locate nested controls by ID.

Example recursive finder (safe, simple):

private Control FindControlRecursive(Control root, string id)
{
    if (root == null) return null;
    if (root.ID == id) return root;
    foreach (Control c in root.Controls)
    {
        Control found = FindControlRecursive(c, id);
        if (found != null) return found;
    }
    return null;
}

Usage:

TextBox tb = FindControlRecursive(ph_Uc_AddModule, "tb3_AddModule") as TextBox;
if (tb != null) string val = tb.Text;

Quick debugging tips: set a breakpoint in OnInit to confirm CreateAddDynamicTable runs on postback, inspect the control tree in the debugger, and always null-check before reading Text. If you expect many dynamic fields, consider a data-bound approach (Repeater/GridView) for simpler lifecycle handling.

Recommended Answers

All 2 Replies

You should have to create public properties in User control.

For instance,

public String Name
{
  get{ return txtName.Text;}
  set { txtName=value;}
}

thanks for the reply.
Actually, i just create the table at the run time dynamically and the number of the columns are not fix each module has different number of column. how to create public properties for this situation which i don't know the type and number of columns.
regards

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.