Access text box value created dynamically when check box is checked - c#

I am a litle confused with ASP.NET lifecycle event. I have a checkbox when it is checked, it will dynamically create labels and text boxes. This is done in checkbox oncheckchanged event.I have Ajax enabled on the checkbox without full postback.
Now in the newly created text boxes I am entering the values and when I click on the save button, in the button click event it would not even find the controls created. So how does the page viewstate remember the dynamic controls created in the checkbox events and then access it's values in the button save event?
Mark up:
<tr> <td> <asp:CheckBox ID="chkType" runat="server" Text="Medical Procedure" OnCheckedChanged="ChkMedicalProc_Clicked"></td></tr>
<tr><td colspan="2">
<asp:PlaceHolder ID="dyna" EnableViewState="true" runat="server"></asp:PlaceHolder>
</td></tr>
Code behind in the checkedchanged event:
TableRow tr = new TableRow();
TableCell tc1 = new TableCell();
TableCell tc2 = new TableCell();
Label lbl = new Label();
lbl.Text = string.Empty;
lbl.Text = (_queryParam[i].Param_Name + " (" + _queryParam[i].Param_Type + ") (" + _queryParam[i].Param_Length + ")").ToString();
lbl.Style.Add("font-size", "11px");
lbl.Style.Add("font-family", "Arial");
_txtBox = new TextBox();
_txtBox.ID = ctrlId;
_txtBox.CssClass = "textEntry";
_txtBox.Text = string.Empty;
_txtBox.Text = _queryParam[i].Param_Value;
tc1.Style.Add("width", "21.8%");
tc1.Controls.Add(lbl);
tc2.Controls.Add(_txtBox);
tr.Cells.Add(tc1);
tr.Cells.Add(tc2);
_tbl.Rows.Add(tr);
this.Master.FindControl("pagecontent1").FindControl("dyna").Controls.Add(_tbl);
Save button click event:
for (int i = 0; i < box.Count; i++)
{
TextBox boxValue= this.Page.Master.FindControl("pagecontent1").FindControl("dyna").FindControl("txtBoxParams-" + i) as TextBox;
//I get object reference error on boxValue
}

Dynamic controls are lost on postback, so on every page request you must dynamically add them again.
Though for your example, it might be easier to always have the label / textbox on the page, but contain it in an asp:panel which you toggle the Visible property on it, or show/hide it via javascript.
As for the values of these dynamic controls during postback, if you re-create them using the same ID, asp.net will automatically re-initialize them to the proper inputted values using the viewstate information.
For more information about dealing with dynamic controls, this website seems to be fairly accurate: https://web.archive.org/web/20211020131055/https://www.4guysfromrolla.com/articles/081402-1.aspx

Using the following recursive function you will be able to retrieve any control inside the dynamic table
public static Control DeepFindControl(Control c, string id)
{
if (c.ID == id)
{
return c;
}
if (c.HasControls())
{
Control temp;
foreach (var subcontrol in c.Controls)
{
temp = DeepFindControl((Control)subcontrol, id);
if (temp != null)
{
return temp;
}
}
}
return null;
}
to receive the values of the control after finding it you should know the name of the control and then you will receive the values in another new created control with the same type... "cast the control returned from the DeepFindControl" e.g....
Control C1 = DeepFindControl(DynamicTableName, ControlNAme);
TextBox _txtBox = (TextBox)C1;

Related

Odd behavior with dynamically created usercontrols on postback

I'm having some difficulty with my dynamically generated usercontrols retaining their selected values. I have created a usercontrol with several form fields. On the main page I have a button that will place my usercontrol in a placeholder. The user can create as many of these as needed. I also have a button in the control itself that allows the user to delete any given control. This functionality seems to be working fine.
But, weirdness ensues in the following scenario:
Click button to create a usercontrol on page. Fill out the form
fields.
Click button again to create a second UC and fill out form
fields. All is well at this point. Values in UC#1 retained its
values.
Click button to create third UC and all selected values are
wiped out of UC #1 and #2.
If I refill out the fields in all the UC's then click the button to create a 4th UC, then UC#1 and UC#3 retain their values but UC#2 loses it's values.
Any help would be massively appreciated. I'm going bug-eyed trying to figure this one out. This is my first foray into dynamic usercontrols and so far it's kicking my butt. And I still have to figure out how to populate these UC's with values from the db so the user can come back and edit the form, but one thing at a time.
aspx:
<asp:PlaceHolder ID="placeholderOffenseCodes" runat="server"> </asp:PlaceHolder>
<asp:Button ID="btnAddOffense" runat="server" Text="Add an Offense" CausesValidation="false" OnClick="btnAddOffense_Click" />
<!--The text value determines how many items are initially displayed on the page-->
<asp:Literal ID="ltlCount" runat="server" Text="0" Visible="false" />
<asp:Literal ID="ltlRemoved" runat="server" Visible="false" />
aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
AddAndRemoveDynamicOffenseControls();
}
private void AddAndRemoveDynamicOffenseControls()
{
//Determine which control fired the postback event.
Control c = GetPostBackOffenseControl(Page);
if ((c != null))
{
//If the add button was clicked, increase
//the count to let the page know we want
//to display an additional user control
if (c.ID.ToString() == "btnAddOffense")
{
ltlCount.Text = Convert.ToString(Convert.ToInt16(ltlCount.Text) + 1);
}
}
//Be sure everything in the placeholder control is cleared out
placeholderOffenseCodes.Controls.Clear();
int ControlID = 0;
//Re-add controls every time the page loads.
for (int i = 0; i <= (Convert.ToInt16(ltlCount.Text) - 1); i++)
{
IncidentGroupA_Offenses uc = (IncidentGroupA_Offenses)LoadControl("IncidentGroupA_Offenses.ascx");
//If this particular control id has been deleted
//from the page, DO NOT use it again. If we do, it will
//pick up the viewstate data from the old item that
//had this control id, instead of generating
//a completely new control. Instead, increment
//the control ID so we're guaranteed to get a "new"
//control that doesn't have any lingering information in the viewstate.
while (InDeletedOffenseList("offense" + ControlID) == true)
{
ControlID += 1;
}
//Note that if the item has not been deleted from the page,
//we DO want it to use the same control id
//as it used before, so it will automatically maintain
//the viewstate information of the user control
//for us.
uc.ID = "offense" + ControlID;
//Add an event handler to this control to raise
//an event when the delete button is clicked
//on the user control
uc.RemoveOffenseUC += this.HandleRemoveOffenseUserControl;
//Add the user control to the panel
placeholderOffenseCodes.Controls.Add(uc);
//Add Offense number to label on usercontrol
int OffenseNum = i + 1;
uc.OffenseNumber = "Offense " + OffenseNum;
//Increment the control id for the next round through the loop
ControlID += 1;
}
}
protected void btnAddOffense_Click(object sender, EventArgs e)
{
//handled in page_load
}
private bool InDeletedOffenseList(string ControlID)
{
//Determine if the passed in user control ID
//has been stored in the list of controls that
//were previously deleted off the page
string listvalues = ltlRemoved.Text;
string[] stringSeparators = new string[] { "|" };
string[] DeletedList = listvalues.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i <= DeletedList.GetLength(0) - 1; i++)
{
if (ControlID == DeletedList[i])
{
return true;
}
}
return false;
}
public void HandleRemoveOffenseUserControl(object sender, EventArgs e)
{
//This handles delete event fired from the user control
//Get the user control that fired this event, and remove it
LinkButton linkBtn = sender as LinkButton;
IncidentGroupA_Offenses uc = (IncidentGroupA_Offenses)linkBtn.Parent;
if (uc != null)
{
placeholderOffenseCodes.Controls.Remove(uc);
}
//Keep a pipe delimited list of which user controls were removed. This will increase the
//viewstate size if the user keeps removing dynamic controls, but under normal use
//this is such a small increase in size that it shouldn't be an issue.
ltlRemoved.Text += uc.ID.ToString() + "|";
//Also, now that we've removed a user control decrement the count of total user controls on the page
ltlCount.Text = Convert.ToString(Convert.ToInt16(ltlCount.Text) - 1);
}
public Control GetPostBackOffenseControl(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if ((ctrlname != null) & ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control c = page.FindControl(ctl);
if (c is System.Web.UI.WebControls.Button)
{
control = c;
break;
}
}
}
return control;
}
.ascx.cs:
public event EventHandler RemoveOffenseUC;
protected void btnRemoveOffense_Click(object sender, EventArgs e)
{
//Raise this event so the parent page can handle it
if (RemoveOffenseUC != null)
{
RemoveOffenseUC(sender, e);
}
}
public string OffenseNumber
{
get { return lblOffenseNumber.Text; }
set { lblOffenseNumber.Text = value; }
}
I always thought you had to add dynamic controls at Page_Init to ensure correct loading of ViewState. Maybe that simple change would fix your problem?
Otherwise, I've had luck in the past with avoiding dynamic controls altogether using a repeater. Instead of adding dynamic controls, which webforms is definitely not very good at, add data to a data structure like a List or ADO DataTable, then bind that to an asp:Repeater with the controls you want in it. No messy fussing around with dynamic controls.
Best of luck!

Dynamically created TextBoxes in a Table lost Text value

I have a Table dynamically generated and inside of 2 columns there are TextBoxes. During the postback the Textboxes are always empty even if I fill them.
The table is builted in this way:
protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtRighe = oTab.getScaleTaglieRighe(ddlScalaTaglie.SelectedValue);
//dt is datatable object which holds DB results.
Table tbl = new Table();
tbl.CssClass = "table table-striped table-bordered table-responsive";
TableRow tr;
TableCell tcEU, tcUS, tcUK, tcQty, tcEAN;
Label lbEU, lbUS, lbUK, lbQty, lbEAN;
TextBox tbEU, tbUS, tbUK, tbQty, tbEAN, tbToFocus = null;
foreach (DataRow dr in dtRighe.Rows)
{
tr = new TableRow();
//ean
tcEAN = new TableCell();
tbEAN = new TextBox();
tbEAN.ID = "txtEAN" + dr[0].ToString();
tbEAN.Width = new Unit(100, UnitType.Percentage);
tbEAN.Columns = 15;
tcEAN.Controls.Add(tbEAN);
tr.Controls.Add(tcEAN);
//Qty
tcQty = new TableCell();
tbQty = new TextBox();
tbQty.ID = "txtQty" + dr[0].ToString();
tbQty.TextMode = TextBoxMode.Number;
tcQty.Controls.Add(tbQty);
tr.Controls.Add(tcQty);
tbl.Controls.Add(tr);
}
Session["tbl"] = tbl;
divTaglieRighe.Controls.Add(tbl);
}
When I click the button SAVE, I have to loop throug my table and save all the TextBox.Text...
this is what I wrote:
ArrayList arrScarpaFigli = new ArrayList();
Table tbl = (Table)Session["tbl"];
foreach (TableRow row in tbl.Rows)
{
foreach (TableCell cell in row.Cells)
{
foreach (Control ctrl in cell.Controls)
{
//CONTROL IS TEXBOXT: EXTRACT VALUES//
if (ctrl is TextBox)
{
TextBox txt = (TextBox)ctrl;
arrScarpaFigli.Add(txt.Text);
}
}
}
}
The problem is that, also if I fill the textboxes, in my Text there is always an empty string.
The only moment when I fill the table is on the selectionChange of a Dropdown.
What I'm doing wrong?
Thanks in advance
You have to recreate dynamic controls on every page load to make sure their values are retained after a PostBack. So you need to create a new Method that handles the creation of the Table every time the page is loaded.
protected void Page_Load(object sender, EventArgs e)
{
//always create the controls on every page load if there is a value selected in ddlScalaTaglie
if (!string.IsNullOrEmpty(ddlScalaTaglie.SelectedValue))
{
createTable(ddlScalaTaglie.SelectedValue);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
//use findcontrol to find the Table inside the placeholder
Table tbl = Page.FindControl("divTaglieRighe").FindControl("Table1") as Table;
//loop all rows and cells in the Table
foreach (TableRow row in tbl.Rows)
{
foreach (TableCell cell in row.Cells)
{
foreach (Control ctrl in cell.Controls)
{
//the control is a textbox
if (ctrl is TextBox)
{
//cast the control back to a textbox
TextBox tb = ctrl as TextBox;
//does the checkbox have a value, if so append the label
if (!string.IsNullOrEmpty(tb.Text))
{
Label1.Text += tb.Text + "<br>";
}
}
}
}
}
}
protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
{
//no need to create the Table dynamically, that will be handled in Page_Load
//this method is just a dummy to trigger a PostBack
//you could remove this method and the OnSelectedIndexChanged from the DropDown
//and just keep the AutoPostBack="true", that will also work
}
private void createTable(string value)
{
DataTable dtRighe = Common.LoadFromDB();
//create a new table WITH id, that is needed for findcontrol
Table tbl = new Table();
tbl.ID = "Table1";
//loop all rows in the datatable
foreach (DataRow dr in dtRighe.Rows)
{
TableRow tr = new TableRow();
//ean
TableCell tcEAN = new TableCell();
TextBox tbEAN = new TextBox();
tbEAN.ID = "txtEAN" + dr[0].ToString();
tbEAN.Width = new Unit(100, UnitType.Percentage);
tbEAN.Columns = 15;
tcEAN.Controls.Add(tbEAN);
tr.Controls.Add(tcEAN);
//Qty
TableCell tcQty = new TableCell();
TextBox tbQty = new TextBox();
tbQty.ID = "txtQty" + dr[0].ToString();
tbQty.TextMode = TextBoxMode.Number;
tcQty.Controls.Add(tbQty);
tr.Controls.Add(tcQty);
tbl.Controls.Add(tr);
}
//add the table to the placeholder
divTaglieRighe.Controls.Add(tbl);
}
The aspx to make the example complete
<asp:DropDownList ID="ddlScalaTaglie" runat="server" OnSelectedIndexChanged="ddlScalaTaglie_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Text="Select..." Value=""></asp:ListItem>
<asp:ListItem Text="Option 1" Value="1"></asp:ListItem>
<asp:ListItem Text="Option 2" Value="2"></asp:ListItem>
</asp:DropDownList>
<br />
<br />
<asp:PlaceHolder ID="divTaglieRighe" runat="server"></asp:PlaceHolder>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Save" OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
Storing an instance of Table control in Session is a terrible idea and is just plain wrong. Controls belong to their parent page - they should be added to it as soon as they are created and they should die with their parent page.
The thing with dynamically created controls in ASP.NET is that you have to store an indicator of the fact that they were created (together with relevant information needed to create them again) and recreate them on all subsequent postbacks - no later than in Page_Load. Only then these controls will have the chance of getting their values from Request and you will have the chance of obtaining these values from controls.
In your code, the instance of Table stored in Session (together with all its rows, cells and textboxes) will never reflect any client-side data changes, nor will it belong to Pages that will be created to process subsequent postback requests.
Update
The important fact to understand here is that, after processing the postback caused by ddlScalaTaglie change and returning hew html to the client, the page instance is gone. On next request a new instance of your page is created - and it does not know anything about the fact that the previous instance had table added to its control tree. It is your code in Page_Load that must discover that the form must have this table, and create the table in exactly the same way it was created the first time - with rows, cells and textboxes with exactly the same IDs.
Then, after you add this newly created table to divTaglieRighe.Controls, the textboxes will be able to extract their client-side values from Request.Form collection.
Make sure the textbox has a "name" for the post back to the controller.
If it does not it grabs a null for the parameter.
Check Request.Form for data returned to controller.
You've created a Table called tbl and added two TextBox, then you store Table control in session Session["tbl"] and added to divTaglieRighe control. Finally you are trying to get TextBox data from your session Session["tbl"] table not the ViewState control that added in divTaglieRighe control. You have to get data from you Table tbl control that added in divTaglieRighe control.

How preserve the values accessing dynamic controls

Hello everybody and thanks in advance,
I´ve read several threads about but I'm very confused. The thing is I'm dynamically creating some textboxes inside a panel control which is placed inside a formview whith this code...
protected void Muestra_Precio_Stock_BT_Click(object sender, EventArgs e)
{
CheckBoxList FormatosCL = (CheckBoxList)FormViewDiscos.FindControl("FormatosCL");
Panel Precio_Stock_PN = (Panel)FormViewDiscos.FindControl("CB_Precio_Stock_PN");
Label NuevoPrecioLB = null;
TextBox NuevoPrecioTB = null;
Label NuevoStockLB = null;
TextBox NuevoStockTB = null;
foreach (ListItem item in FormatosCL.Items)
{
if(item.Selected)
{
NuevoPrecioLB = new Label();
NuevoPrecioTB = new TextBox();
NuevoStockLB = new Label();
NuevoStockTB = new TextBox();
NuevoPrecioLB.ID = "NuevoPrecioLB_" + FormatosCL.Items.IndexOf(item);
NuevoPrecioLB.Text = "PRECIO " + item.Text + ": ";
NuevoPrecioTB.ID = "NuevoPrecioTB_" + FormatosCL.Items.IndexOf(item);
NuevoStockLB.ID = "NuevoStockLB_" + FormatosCL.Items.IndexOf(item);
NuevoStockLB.Text = " STOCK " + item.Text + ": ";
NuevoStockTB.ID = "NuevoStockTB_" + FormatosCL.Items.IndexOf(item);
Precio_Stock_PN.Controls.Add(NuevoPrecioLB);
Precio_Stock_PN.Controls.Add(NuevoPrecioTB);
Precio_Stock_PN.Controls.Add(NuevoStockLB);
Precio_Stock_PN.Controls.Add(NuevoStockTB);
Precio_Stock_PN.Controls.Add(new LiteralControl("<br />"));
}
}
}
Well, this works well, when I run the project the textboxes and labels are created as expected, I can see them and write into the textboxes. I`ve put the same code into Page_Load event and now I can get the created controls and avoid the nullpointerexception (that was my first problem) when I click the INSERT button of the formview. The problem is that, in the following code...
protected void InsertButton_Click(object sender, EventArgs e)
{
TextBox DiscIdTB = (TextBox)FormViewDiscos.FindControl("DiscIdTB");
TextBox CaratulaTB = (TextBox)FormViewDiscos.FindControl("CaratulaTB");
CheckBoxList CancionesCL = (CheckBoxList)FormViewDiscos.FindControl("CancionesCL");
CheckBoxList FormatosCL = (CheckBoxList)FormViewDiscos.FindControl("FormatosCL");
using (SqlConnection conexion = new SqlConnection(ConfigurationManager.ConnectionStrings["ConexionBBDD-Discos"].ConnectionString))
{
conexion.Open();
cmd.Connection = conexion;
cmd.CommandText = "INSERT INTO DISCOS_FORMATOS (ID_DISCO, ID_FORMATO, PRECIO, STOCK) VALUES ((SELECT MAX(ID_DISCO) FROM DISCOS), #IdFormato, 0, 0)";
foreach (ListItem item in FormatosCL.Items)
{
if (item.Selected)
{
Panel Precio_Stock_PN = (Panel)FormViewDiscos.FindControl("CB_Precio_Stock_PN");
string control = "NuevoPrecioTB_" + (FormatosCL.Items.IndexOf(item));
string control2 = "NuevoStockTB_" + (FormatosCL.Items.IndexOf(item));
TextBox Precio = (TextBox)Precio_Stock_PN.FindControl(control);
TextBox Stock = (TextBox)Precio_Stock_PN.FindControl(control2);
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#IdFormato", item.Value);
cmd.Parameters.AddWithValue("#IdPrecio", Convert.ToInt32(Precio.Text));
cmd.Parameters.AddWithValue("#IdStock", Convert.ToInt32(Stock.Text));
cmd.ExecuteNonQuery();
}
}
conexion.Close();
cmd.Dispose();
}
}
when the execution reaches these lines, dynamically created textboxes lost their values, returning always 0...
cmd.Parameters.AddWithValue("#IdPrecio", Convert.ToInt32(Precio.Text));
cmd.Parameters.AddWithValue("#IdStock", Convert.ToInt32(Stock.Text));
How can I preserve their user typed values?
Have you tried putting the code in the Page_Load method inside a block with
if (!IsPostBack)
{
//
}
Another thing you can try if this doesn't work is saving the typed-in values in Session variables.
I don't think the InsertButton is important here. By the way, if you use the runat=server on the objects you don't have to use FindControl, the server will be able to manage it. Also for dynamic controls you might want to try a different approach like: GridView (remove headers and it won't look like a grid), a DataList, or a ListView. What goes inside the ItemTemplate are the objects you are repeating/creating dynamically. You can add labels and textboxes here. For example:
<asp:ListView ID="repeatedStuff" runat="server"><ItemTemplate>
</ItemTemplate>
</asp:ListView>
Or
<asp:DataListID="list"
CellPadding="2"
RepeatDirection="Vertical"
RepeatLayout="Table"
RepeatColumns="2"
runat="server">
<ItemTemplate>
<asp:CheckBoxID="cboxP"AutoPostBack="True"runat="server"/>
<asp:Labelrunat="server"Text='<%#Bind("Nombre")%>'ID='<%#Bind("ID")%>'></asp:Label>
</ItemTemplate>
</asp:DataList>
What remains after this approach is managing the binding and how to identify them when an event is triggered. Like adding a textchange event on server side, if you bind the ID value on the event you ask for the sender's ID and then you can know which one is being "textchanged".

How do I handle an event from a dynamically generated button using a modal dialog popup and custom control?

I have a custom control that has a search function. When the user clicks search, the code generates a list of buttons based on the results of the search.
Each button's CommandArgument property contains the Id of the search result. When the user clicks the button, I want to handle the event, get the CommandArgument and raise an event back to the main page with the value.
The problem is that the buttons aren't raising the event. I would assume this is because it gets lost on a postback or whatever. Should I consider an alternative way of listing the values to make this work?
Whats the simplest way of getting around this? Here's what I have:
private void Search()
{
foreach (var c in companies)
{
TableRow companyRow = new TableRow();
TableCell nameRowCell = new TableCell();
TableCell regRowCell = new TableCell();
Button selectButton = new Button();
selectButton.CommandArgument = c.Id.ToString();
selectButton.Text = c.Name;
selectButton.Click += new EventHandler(selectButton_Click);
selectButton.CausesValidation = false;
nameRowCell.Controls.Add(selectButton);
companyRow.Cells.Add(nameRowCell);
tblCompanies.Rows.Add(companyRow);
}
}
void selectButton_Click(object sender, EventArgs e) // <- Not getting handled
{
Button btn = (Button)sender;
string id = btn.CommandArgument;
if (id != "" && CompanyFound != null)
CompanyFound(new Company() { Id = int.Parse(id) });
}
I've been playing with your code and it does put a button on the screen. The browser source shows the button in the form of an input type submit tag. To test that it is in fact firing add a div to your page somewhere, maybe set it's id to testDiv. Then in your selectButton_Click event hander add a line to the effect of: testDiv.innerHtml = "made it here".
If the div changes, your button fired.
Also, maybe add protected, public or something before the void on the selectButton_Click.

How to find a control recursively in ASP.NET

There are lots of examples on this, and I'm pretty sound with the concept of using recursion to find the control. Once the control has been found on postback, it can be interacted with, etc.
I have an empty asp:table in my HTML markup:
<asp:Table ID="editDataTable" runat="server">
</asp:Table>
And on Page_Load the table is populated with many rows and many columns (I am quite proud that I figured that out). Inside some of the table cells there is a <asp:TextBox />.
You've guessed it, I need to get the value of these text boxes!
(I've got the code for recursion and checked it, and it seems good.)
My table has two columns. The left one contains titles like "Company Name, Telephone", etc. and the right column contains text boxes with its respective title's value. So a user can edit the text box (if the telephone number has change for example) and submit the changes.
Obviously the rows are dynamically added depending on the user.
The problem I'm having is: You need to ADD the control to the page when populating the table. Something along the lines of:
myTable.Control.Add(new TextBox());
In my case, my Table is called editDataTable. So in my code where I add the Rows, I've added the control too, as follows.
for (int i = 0; i < rowCount; i++)
{
editDataTable.Rows.Add(tblRow[j]); // This is where I add the ROW to my sexy table
editDataTable.Controls.Add(new TextBox()); // This is where I add the control
}
Those awake amongst you will know that you can't add a text box control to a table!
So finally, my questions are:
How do I add the control for The Text Boxes in my table?
Where do I add them?
Is there any extra advice to help me fulfill my quest of retrieving the text values of my dynamically added text boxes?
Here's my recursive code just in case you were curious:
private void getControls(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c is TextBox && c.ID == null)
{
//Stuff
}
if (c.Controls.Count > 0)
{
getControls(c);
}
}
}
Here is an example of building a dynamic table in ASP.NET during PageLoad, and reading in the values through a postback. Since the table is dynamic, it will NOT be rebuilt when the page is postback to the server. If you want to rebuild the table, you'll need to render it again and use the values you pull in from Request.Form to re-populate it.
HTML Markup
<asp:Table ID="editDataTable" runat="server">
</asp:Table>
<asp:Button runat="server" Text="Submit" OnClick="Submit_Click" />
Code Markup
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string[] dynamicTable = { "First Name", "Last Name", "Address", "Phone" };
foreach (string s in dynamicTable)
{
TableRow row = new TableRow();
// Add First Cell with Text to Row
row.Cells.Add(new TableCell() { Text = s });
// Create Second Cell
TableCell textBoxCell = new TableCell();
// Add Textbox Control to Second Cell
textBoxCell.Controls.Add(new TextBox() { ID = "Dynamic_" + s.Replace(" ","_") });
// Add Second Cell to Row
row.Cells.Add(textBoxCell);
// Add New Row to Table
editDataTable.Rows.Add(row);
}
}
}
protected void Submit_Click(object sender, EventArgs e)
{
for (int i = 0; i < Request.Form.Count; i++)
{
string key = Request.Form.GetKey(i);
if (key.Contains("Dynamic_"))
{
Response.Write("<p><strong>" + (key.Remove(0,8)).Replace("_"," ") + "</strong> :: " + Request.Form[i] + "</p>");
}
}
}
You need to add a TableCell to the TableRow.Cells collection, and add the TextBox to the TableCell.Controls collection:
TableCell cell = new TableCell();
cell.Controls = new TextBox();
tblRow[j].Cells.Add(cell);
editDataTable.Rows.Add(tblRow[j]);
The most direct way to access the textboxes is to keep them all in a list:
List<TextBox> textBoxes = new List<TextBox>();
and replace cell.Controls = new TextBox(); above with this:
TextBox tb = new TextBox();
textBoxes.Add(tb);
cell.Controls = tb;
And then you can iterate through the textBoxes afterward without having to search for them in a tree.

Categories

Resources