I have a problem that I believe is a session state issue, but I'm at a loss to figure out what's wrong. I have a sample project to illustrate the problem. (Code below) I have 2 buttons. Each populates a List with some unique data and then uses that data to add a row to a table. The row contains text boxes so that the user can edit the data. (For my sample, there's no update button to persist the data.) To reproduce the problem in VS2010, create a new "ASP.NET Web Application" project and copy/paste the aspx code and the c# code-behind into Default.aspx, then run the application.
Press the DataSet 1 button and the grid should populate with 1 row.
Edit the data in one of the text boxes and tab off of the text box. (The newly entered text should remian, and the font should be blue. This is what I want to happen.)
Now click either of the DataSet buttons to reset the List and refresh the table.
Edit the data in one of the text boxes and tab off the text box. (Immediately, the text in the box refreshes back to its original value. This only happens once, though. If you edit either text box now, it will work normally.)
This is repeatable... the first edit after pressing the DataSet buttons a 2nd, 3rd, etc. time gets reset back to the original value. And I can't figure out why.
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="DebugPostbackIssue._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
Populate the table with DataSet #1:<asp:Button runat="server" ID="btnDS1" Text="Dataset 1" OnClick="btnDS1_Click" />
</p>
<p>
Populate the table with DataSet #2:<asp:Button runat="server" ID="btnDS2" Text="Dataset 2" OnClick="btnDS2_Click" />
</p>
<p>
<asp:Table runat="server" ID="tblData">
<asp:TableHeaderRow runat="server" ID="thrData">
<asp:TableHeaderCell Scope="Column" Text="Column 1"></asp:TableHeaderCell>
<asp:TableHeaderCell Scope="Column" Text="Column 2"></asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</p>
</asp:Content>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DebugPostbackIssue
{
public partial class _Default : System.Web.UI.Page
{
private List<string> _MyData = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
LoadSessionData();
GenerateGrid(false);
}
protected void btnDS1_Click(object sender, EventArgs e)
{
_MyData = new List<string>();
_MyData.Add("111");
_MyData.Add("aaa");
SaveSessionData();
GenerateGrid(true);
}
protected void btnDS2_Click(object sender, EventArgs e)
{
_MyData = new List<string>();
_MyData.Add("222");
_MyData.Add("bbb");
SaveSessionData();
GenerateGrid(true);
}
private void SaveSessionData()
{
Session["MyData"] = _MyData;
}
private void LoadSessionData()
{
if (Session["MyData"] != null)
_MyData = (List<string>)Session["MyData"];
else
_MyData = new List<string>();
}
private void GenerateGrid(bool ClearData)
{
if (ClearData)
while (tblData.Rows.Count > 1)
tblData.Rows.Remove(tblData.Rows[tblData.Rows.Count - 1]);
TableRow tr = new TableRow();
foreach (string s in _MyData)
{
TableCell tc = new TableCell();
TextBox txtBox = new TextBox();
txtBox.Text = s;
txtBox.Attributes.Add("OriginalValue", s);
txtBox.TextChanged += new EventHandler(txtBox_TextChanged);
txtBox.AutoPostBack = true;
tc.Controls.Add(txtBox);
tr.Cells.Add(tc);
}
if (tr.Cells.Count > 0)
tblData.Rows.Add(tr);
}
void txtBox_TextChanged(object sender, EventArgs e)
{
TextBox Sender = (TextBox)sender;
if (Sender.Text == Sender.Attributes["OriginalValue"])
Sender.ForeColor = System.Drawing.Color.Black;
else
Sender.ForeColor = System.Drawing.Color.Blue;
}
}
}
Hi I took some time off of my work to compile your code, and I figured it out, just change your textbox change to the following :
void txtBox_TextChanged(object sender, EventArgs e)
{
TextBox Sender = (TextBox)sender;
if (Sender.Text == Sender.Attributes["OriginalValue"])
Sender.ForeColor = System.Drawing.Color.Black;
else
{
Sender.ForeColor = System.Drawing.Color.Blue;
if (Session["MyData"] != null)
{
List<string> _ss = (List<string>)Session["MyData"];
//_ss.Find(a => a == Sender.Attributes["OriginalValue"]);
_ss.Remove(Sender.Attributes["OriginalValue"]);
_ss.Add(Sender.Text);
}
}
}
ur welcome!
Try creating a datatable. I would, on "event" copy your asp table content to a datatable, then when you get the servers response add that to the datatable. Then copy the datatable back to your asp table, and repeat... Datatables can be used like variables.
Or try using a cookie.
Try changing...
protected void Page_Init(object sender, EventArgs e)
{
LoadSessionData();
GenerateGrid(false);
}
To...
protected override void OnLoadComplete(EventArgs e)
{
LoadSessionData();
GenerateGrid(false);
}
Based on your description I believe that your value is getting reset because of how the page life cycle works in ASP.NET & that is the page_init is getting called before your event due to ASP.NET quirkiness. Above code is how I work around it, I'm sure there's other ways too.
Okay, I have it working, now. Wizpert's answer pointed me in the right direction... Upon discovering that the TextChanged event did not fire during the times when the value was erroneously being reset to the original value, it occurred to me that during the Click events I was calling GenerateGrid(true). This forced the removal of the existing rows and the addition of new rows. (Removing & adding the dynamic controls at that point in the life cycle must be interfering with the TextChange event handler.) Since the Click event fires after Page Init and after Page Load, the state values were already written to the text boxes and I was overwriting them. But the 2nd text box edit did not force GenerateGrid(true) to be called so the state values were not overwritten any more.
If this sounds confusing, I apologize. I'm still wrapping my head around this. But suffice to say that I had to change my GenerateGrid method to reuse any existing rows and not delete them. (If they don't exist, like when GenerateGrid is called from Page Init, then they are added.) So this was a page lifecycle issue after all.
Thank you.
Related
I tried doing this on the check box list page:
protected void Page_Load(object sender, EventArgs e)
{
(string)Session["name"] = cbl1.Items.Add;
}
but I don't know how to make it work.
You don't really "put a label into" a check box list from another page.
You might say have a check box list on one page, and you want to pass the selection(s) made in the first page, and pass to the 2nd page.
So, say we have a simple check box list of options on page 1
And a button to jump to the next page.
This markup:
<h3>Hotel Options</h3>
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
DataValueField ="ID"
DataTextField="HotelOption" >
</asp:CheckBoxList>
<br />
<br />
<asp:Button ID="Button1" runat="server"
Text="Continue to next page" CssClass="btn" OnClick="Button1_Click" />
And code to load this up:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadCheckBox();
}
void LoadCheckBox()
{
DataTable rstOptions =
MyRst("SELECT ID, HotelOption FROM tblOptions ORDER BY ID");
CheckBoxList1.DataSource = rstOptions;
CheckBoxList1.DataBind();
}
DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.Hotels))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Connection.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
And we now have this:
Ok, so now our code for the button.
We will get + save the above selections, and pass to the next page:
protected void Button1_Click(object sender, EventArgs e)
{
Session["MyItems"] = CheckBoxList1.Items;
Response.Redirect("WebForm2.aspx");
}
Ok, now our markup for the 2nd page.
We have this:
<h3>Hotel Options - on next page</h3>
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
DataValueField ="Value"
DataTextField="Text" >
</asp:CheckBoxList>
<br />
Now, we saved the "items list" for the Check box list. The item list has a text and value property (we LOSE the colum name information that the data sourced used was).
So, note how the DataValueField="value" and DataTextField="Text" now.
So, this code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadCheckBox();
}
void LoadCheckBox()
{
ListItemCollection MyItems = (ListItemCollection)Session["MyItems"];
foreach (ListItem OneItem in MyItems)
{
CheckBoxList1.Items.Add(OneItem);
}
}
And now on 2nd page we have this:
Now it is NOT clear why I can't just bind this passed list directly to the check box list, but I found a foreach loop is required.
Now, it is perhaps not clear, but maybe you ONLY wanted the label text ones selected.
You can do this with this code:
ListItemCollection MyItems = (ListItemCollection)Session["MyItems"];
foreach(ListItem OneItem in MyItems)
{
if (OneItem.Selected)
{
Debug.Print("Label text = " + OneItem.Text);
Debug.Print("Check box value = " + OneItem.Value);
}
}
Output:
Label text = Smoking
Check box value = 1
Label text = Balcony
Check box value = 2
So, keep in mind that a check box list can often have 2 columns of data.
The display "label" or text, or the hidden value.
In my example, the "ID" is the PK value from the database, and I need that.
If you only have one "text" value, and don't care about a hidden database PK value, then often I just set both DataTextField and DataValueField to the SAME column in the database.
And if you using looping, and adding a listitem in code? Then the settings are not the field columns anymore, but Text and Value. You thus still have the ability to have 2 values - the display text, and some key or number value for a checkbox list.
Now perhaps you have two web pages open, and you want to change/set controls in the other web page?
No, you can't do that. Other web pages might say be open to someone's banking web site. You can't mess around with other web pages the user has open, since that would be a MASSIVE security hole, and no one would risk using the world wide web then, right?
Edit: placing the results on a label on the 2nd page
Ok, so the debug.print? That is just a handy debugging way of displaying some code values - only for developers. It really much like using console.log to display value(s) into the console. It certainly not for putting some text into a label (I realy thought that would be crystail clear to you - at a loss as to why you think debug.print has anything of value or is relavent to YOU writing code to put a few text values into a label).
So, ok, on the 2nd page we will have a label and not some check box list.
So, our markup on the 2nd page will now look like this:
<asp:Label ID="Label1" runat="server" Text=""
Font-Bold="true"
Font-Size="Large"
></asp:Label>
And in our page load event, we will have this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadLabel();
}
void LoadLabel()
{
ListItemCollection MyChoices = (ListItemCollection)Session["MyItems"];
// process selection list from
// previous page - shove reuslts into label
string strChoices = "";
foreach (ListItem OneChoice in MyChoices)
{
if (OneChoice.Selected)
{
if (strChoices != "")
strChoices += ",";
strChoices += OneChoice.Text;
}
Label1.Text = strChoices;
}
}
So, now on first page, we say select this:
And now on 2nd page, we see this:
Of course, we could change our code to display each choice on a new line,
Say this code:
void LoadLabel()
{
ListItemCollection MyChoices = (ListItemCollection)Session["MyItems"];
// process selection list from
// previous page - shove reuslts into label
string strChoices = "";
foreach (ListItem OneChoice in MyChoices)
{
if (OneChoice.Selected)
{
if (strChoices != "")
strChoices += #"<br/>"; // <-- new line in label
strChoices += OneChoice.Text;
}
Label1.Text = strChoices;
}
}
And now we would see this:
So, you can shove results into that label - separated by ",", or whatever.
Or, you can display the choices on a new line as per last example.
Do web controls ever appear like you are changing their values but actually retain the previous value?
I created a pop-up modal for users to edit an item. When the user clicks edit on an item on the main page, the following sequence happens:
The item's ID is passed to the Page_Load event of the modal page, and is used to populate the page control's with the item's data.
The user changes a value in a control. Ex: Changes text in a TextBox contol.
The user clicks save, triggering the Click event which creates a DataTransferObject with the values in the textboxes, which will be stored.
However, on step 3, the control's new value (TextBox.Text) still holds the value that it orginially had, not the value the user put in.
Add.aspx:
<%# MasterType VirtualPath="../MasterPages/Popup.Master" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:TextBox ID="TextBoxDescription" runat="server"></asp:TextBox>
<telerik:RadButton ID="btnSave" runat="server" Text="Save" OnClick="btnSave_Click"/>
</asp:Content>
Add.aspx.cs
//Cannot access the new values here
protected void btnSave_Click(object sender, EventArgs e)
{
//This will print the new text on Create, but the old text on Edit
System.Diagnostics.Debug.WriteLine(TextBoxDescription.Text);
}
//works properly
protected void Page_Load(object sender, EventArgs e)
{
objIDParam = Convert.ToInt64(Request.QueryString["ObjectID"]);
editMode = (objIDParam != 0) ? true : false;
if(editMode)
PopulateFields(objID);
}
//works properly
private void PopulateFields(long objID)
{
MyObject obj = GetObjectByID(objID);
TextBoxDescription.Text = obj.Description;
}
It is worth noting that this popup page is used for both creating items AND editing items. Create works fine (i.e. The item isn't saved with all blanks, but rather the user input). Editing an item will properly pull all that data back in, and let the user edit the fields, however I can't access the changed values in my code.
You need to check for IsPostBack in the Page_Load method.
The Page_Load gets called before the btnSave_Click method, so the TextBoxDescription.Text is getting reset to obj.Description before the btn_Save method runs.
Try returning out of Page_Load if you're posting back:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
objIDParam = Convert.ToInt64(Request.QueryString["ObjectID"]);
editMode = (objIDParam != 0) ? true : false;
if(editMode)
PopulateFields(objID);
}
Have a look at ASP.NET Page Life Cycle Overview for more info.
I'm working on a page that uses a repeater to display a list of custom controls, each containing two dropdown lists.
On a click on the Add control button, the page adds a new row on the repeater, and a click on one of the Delete control buttons embedded in each control removes the relevant control from the repeater.
The delete part seems to work, (setting NamingController.Visible to false), but the add part fails, as once I add the new control, a call to a new repeater.DataBind() loses all viewstate data, preventing the dropdownlists from retrieving the values they had before postback.
Is there a way to manually bind the added control to the repeater without calling a full databind ? Or is there any other way to add a control without losing data ?
Here's some code (I only left what seems relevant, please let me know if you think I forgot to specify something) :
Page.aspx:
<asp:Button ID="addControl" runat="server" Text="Add control" />
<asp:Repeater ID="repeater" runat="server" OnItemDataBound="repeater_ItemDataBound">
<ItemTemplate>
<uc:CustomControlWithDropDownLists ID="custom" runat="server" />
</ItemTemplate>
</asp:Repeater>
Page.aspx.cs:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
repeater.DataSource = GetDataSource();
repeater.DataBind();
}
protected void Page_Init(object sender, EventArgs e)
{
addControl.Click += (sndr, args) =>
{
// Create the object we want to bind to the repeater
ObjectToBind objectToBind = new ObjectToBind();
// Here is what causes data loss
((IList<ObjectToBind>)repeater.DataSource).Add(objectToBind);
repeater.DataBind();
};
}
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// Do some stuff
}
}
CustomControlWithDropDownLists.ascx:
<%-- Some dropdown lists --%>
<asp:Button ID="deleteControl" runat="server" Text="Delete control" />
CustomControlWithDropDownLists.ascx.cs:
protected void Page_Init(object sender, EventArgs e)
{
deleteControl.Click += (sndr, args) =>
{
// ... Delete the control ...
((Button)sndr).NamingContainer.Visible = false;
};
}
You are loosing the data because of View state.
View State losses the data when we are redirecting to the another page.
View state only store the data for the specific page.
The moment you go to another page data is lost by view state.
& there are many chances of losing the data on the same page because of many reasons.
So, the best way to store the data is to use session variable.
Session stores the data even when you are redirecting to the another page.
It is the best way to store the data.
By default it stores the data for 20 minutes.
I hope this will solve your issue.
I had done something similar in the past and found this link from c-sharp corner helpful.
http://www.c-sharpcorner.com/Blogs/10913/add-dynamic-row-using-repeater.aspx
The key element for me if memory servers is using the ViewState object and binding accordingly.
myObject = ViewState["MyData"]; etc.
( I am sorry I don't have access to my code at the moment )
I have spend two days trying to figure out the solution to this problem, even tried ExpertExchange and still I can't get a solution. I am a very novice programmer to ASP.Net (using C#) and I DON'T want to use a string/url post
I have a MasterPage of which has a textbox called tbSearchString. It is a simple box that a user can enter something and then it does a Postback to another page SearchResults.aspx So I also have other pages, like Default.aspx that uses the MasterPage.
I have tried nearly everything and have read nearly every post I could find on the net and no mater what the Variables are always Null.
I have use this code on the searchResults loadpage event and Every one of these variables are null, even though I enter a value in the page text box and click the button to postback to the SearchResults page, the only time it works is if I am on the searchResults page and submit.
SearchResults back end page
protected void Page_Load(object sender, EventArgs e)
{
TextBox SearchString;
TextBox SearchString2;
TextBox SearchString3;
TextBox SearchString5;
if (Page.PreviousPage != null) //This is true on every test
{
SearchString = (TextBox)Page.PreviousPage.Master.FindControl("tbSearchString");
SearchString2 = (TextBox)PreviousPage.Master.FindControl("tbSearchString");
SearchString3 = (TextBox)Master.FindControl("tbSearchString");
TextBox LoginControlx = (TextBox)PreviousPage.FindControl("Form1");
if (LoginControlx != null)
{
TextBox SearchString4 = (TextBox)LoginControlx.FindControl("tbSearchString");
}
}
MainWebsite.Master page Code
<asp:TextBox ID="tbSearchString" runat="server"></asp:TextBox>
<asp:Button ID="btnSearch1" runat="server" Text="Search" PostBackUrl="~/SearchResultRentalEquiptment.aspx" />
I don't have anything in the CS backend page
So on the Default.aspx page
nothing special Just the Masterpage and some text content, I enter some text in the textbox goes to the SearchResults page and I can not get the darn value from the Textbox control from the Default or any other page.
What say you wise ones?
how do you redirect your form to search result form? if you are using Response.redirect, the value under Page.PreviousPage.Master.FindControl will be null . Try to use Server.Transfer to see if it works.
Here's one way:
Assuming this is your Master Page code:
<asp:TextBox ID="searchbox" runat="server" /><br />
<asp:Button ID="sendSearch" runat="server" PostBackUrl="~/Results.aspx" Text="Search" />
At the end of the day, it's all about HTTP POST, so in the target page Results.aspx PageLoad:
protected void Page_Load(object sender, EventArgs e)
{
string _foo = Request.Form[this.Master.FindControl("searchbox").UniqueID];
}
Hth....
Check out Session. I use it all the time when I need to get data from one page to another. I'm not currently able to write out a full example for you, but off the top of my head the following should work:
//page1.aspx:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string greetingString = "Hello";
Session["MyValue"] = greetingString;
Response.Redirect("page2.aspx");
}
//page2.aspx:
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(Session["MyValue"].ToString()); //prints "Hello"
}
<asp:Button onclick="Some_event" Text="Add TextBox" ID="id1" runat="server" />
//once clicked:
<asp:TextBox ID="txt1" ......></asp:TextBox>
//when clicked again:
<asp:TextBox ID="txt1" ......></asp:TextBox>
<asp:TextBox ID="txt2" ......></asp:TextBox>
//and so on...
Is there a way to create dynamic controls which will persist even after the postback? In other words, when the user clicks on the button, a new textbox will be generated and when clicks again the first one will remain while a second one will be generated. How can I do this using asp.net ? I know that if I can create the controls in the page_init event then they will persist but I dont know if it possible to handle a button click before the page_init occurs, therefore there must be another way.
Yes, this is possible. One way to do this using purely ASP.NET (which seems like what you're asking for) would be to keep a count of the TextBox controls that you have added (storing that value in the ViewState) and recreate the TextBox controls in the Page_Load event. Of course, nowadays most people would probably use Javascript or jQuery to handle this task client side, but I put together a quick example to demonstrate how it works with postbacks:
Front page:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicControls.aspx.cs" Inherits="MyAspnetApp.DynamicControls" EnableViewState="true" %>
<!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"></head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAddTextBox" runat="server" Text="Add" OnClick="btnAddTextBox_Click" />
<asp:Button ID="btnWriteValues" runat="server" Text="Write" OnClick="btnWriteValues_Click" />
<asp:PlaceHolder ID="phControls" runat="server" />
</div>
</form>
</body>
</html>
Code behind:
using System;
using System.Web.UI.WebControls;
namespace MyAspnetApp
{
public partial class DynamicControls : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Recreate textbox controls
if(Page.IsPostBack)
{
for (var i = 0; i < TextBoxCount; i++)
AddTextBox(i);
}
}
private int TextBoxCount
{
get
{
var count = ViewState["txtBoxCount"];
return (count == null) ? 0 : (int) count;
}
set { ViewState["txtBoxCount"] = value; }
}
private void AddTextBox(int index)
{
var txt = new TextBox {ID = string.Concat("txtDynamic", index)};
txt.Style.Add("display", "block");
phControls.Controls.Add(txt);
}
protected void btnAddTextBox_Click(object sender, EventArgs e)
{
AddTextBox(TextBoxCount);
TextBoxCount++;
}
protected void btnWriteValues_Click(object sender, EventArgs e)
{
foreach(var control in phControls.Controls)
{
var textBox = control as TextBox;
if (textBox == null) continue;
Response.Write(string.Concat(textBox.Text, "<br />"));
}
}
}
}
Since you are recreating the controls on each postback, the values entered into the textboxes will be persisted across each postback. I added btnWriteValues_Click to quickly demonstrate how to read the values out of the textboxes.
EDIT
I updated the example to add a Panel containing a TextBox and a Remove Button. The trick here is that the Remove button does not delete the container Panel, it merely makes it not Visible. This is done so that all of the control IDs remain the same, so the data entered stays with each TextBox. If we were to remove the TextBox entirely, the data after the TextBox that was removed would shift down one TextBox on the next postback (just to explain this a little more clearly, if we have txt1, txt2 and txt3, and we remove txt2, on the next postback we'll create two textboxes, txt1 and txt2, and the value that was in txt3 would be lost).
public partial class DynamicControls : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
for (var i = 0; i < TextBoxCount; i++)
AddTextBox(i);
}
}
protected void btnAddTextBox_Click(object sender, EventArgs e)
{
AddTextBox(TextBoxCount);
TextBoxCount++;
}
protected void btnWriteValues_Click(object sender, EventArgs e)
{
foreach(var control in phControls.Controls)
{
var panel = control as Panel;
if (panel == null || !panel.Visible) continue;
foreach (var control2 in panel.Controls)
{
var textBox = control2 as TextBox;
if (textBox == null) continue;
Response.Write(string.Concat(textBox.Text, "<br />"));
}
}
}
private int TextBoxCount
{
get
{
var count = ViewState["txtBoxCount"];
return (count == null) ? 0 : (int) count;
}
set { ViewState["txtBoxCount"] = value; }
}
private void AddTextBox(int index)
{
var panel = new Panel();
panel.Controls.Add(new TextBox {ID = string.Concat("txtDynamic", index)});
var btn = new Button { Text="Remove" };
btn.Click += btnRemove_Click;
panel.Controls.Add(btn);
phControls.Controls.Add(panel);
}
private void btnRemove_Click(object sender, EventArgs e)
{
var btnRemove = sender as Button;
if (btnRemove == null) return;
btnRemove.Parent.Visible = false;
}
}
I read an article by Scott Mitchell that explains that ViewState only persists changed control state across post-back, and not the actual controls themselves. I did not have your exact scenario, but a project I was working on required dynamically added user controls and I had to add them on every postback. In that case, it is still useful to create them in Init so that they can retain their state. Here is the link: Understanding ASP.NET View State. Check section “View State and Dynamically Added Controls”.
You may have to keep track of all the controls that you are adding (in session state for example) and re-create them on post back. I just did a small test where I keep a List<string> of all the Textbox ids in Session. On postback, I recreate all the textboxes.