How to retrieve TextBox value in ViewState from its ID - asp.net

I am building many textboxes programmatically in my ASP.NET page, after I've clicked a button, I would like to process those values, is there any possibility to retrieve them from their ID in ViewState ?
Here is my code :
Reference of the table in the aspx :
<asp:Table ID="Distances" runat="server" ViewStateMode="Inherit"></asp:Table>
Then in code behind after creating all the rows and cells, I add a textbox into some of them :
Distances.Rows[j].Cells[i].Controls.Add(CreateTB(distance.ToString(), (i + j * rows).ToString(), false));
protected TextBox CreateTB(string text, string id, bool ebanled = true)
{
TextBox tb = new TextBox() { Text = text, ID = id, Enabled = ebanled};
tb.TextChanged += new EventHandler(OnTBChanged);
return tb;
}

ViewState is enabled by default, so it should already work that the Text property is persisted across postbacks.
So you could for example use FindControl("TextBoxID") or enumerate them to get the refernce to the TextBox (assuming that they are added to a container-control like Panel):
foreach(TextBox txt in MyPanel.Controls.OfType<TextBox>())
{
String text = txt.Text;
}
or
TextBox txt = (TextBox)MyPanel.FindControl("TextBox1")
String text = txt.Text;
I assume you're not recreating those TextBoxes on postbacks. Therefore you need to use the same ID as before and recreate them in Page_Load at the latest stage in page's life-cycle. So you can create them in an event, but you cannot recreate them there.
You should show your code where you create them dynamically, then i could be more specific.
TRULY UNDERSTANDING DYNAMIC CONTROLS

Related

Rows added to gridview don't persist when save event is triggered

I have a gridview on my webpage that can have rows added dynamically. There is a for loop that adds the rows like this:
protected void AddNewJob(object sender, EventArgs e)
{
for(int i = 0; i < Convert.ToInt32(newJobCount.Text);i++)
{
TableRow tr = new TableRow();
tr.Cells.Add(ServicesDDL("-- Select Service Type --"));
tr.Cells.Add(JobsDDL("-- Select Job Type --"));
tr.Cells.Add(TextBoxCell());
tr.Cells.Add(TextBoxCell());
tr.Cells.Add(TextBoxCell());
assetTable.Rows.Add(tr);
}
}
After the rows are added and changed from their default values the rows are looped through and data is saved to the database. I'm having problems getting the rows added to the gridview to persist and exist on the gridview when the page's save event is triggered. That code looks like this:
foreach (TableRow row in assetTable.Rows)
{
if (isFirst)
{
isFirst = false;
continue;
}
DropDownList service = (DropDownList)row.Cells[0].Controls[0];
string assetText = service.SelectedItem.Value;
DropDownList jobDescription = (DropDownList)row.Cells[1].Controls[0];
string serialText = jobDescription.SelectedItem.Value;
TextBox equipmentCount = (TextBox)row.Cells[2].Controls[0];
string leaseText = equipmentCount.Text;
TextBox jobSize = (TextBox)row.Cells[3].Controls[0];
string originText = jobSize.Text;
TextBox serialNo = (TextBox)row.Cells[4].Controls[0];
string deliveryText = serialNo.Text;
string oNo = orderNo.Text;
if (assetText != "0" && serialText != "0")
{
APICallClass.Job j = new APICallClass.Job();
j.JobTypeID = Convert.ToInt32(serialText);
j.serviceID = Convert.ToInt32(assetText);
j.equipment = leaseText;
j.jobSize = originText;
j.serialNumbers = deliveryText;
j.orderID = Convert.ToInt32(global.GlobalID);
APICallClass.API.AddJob(j, Session["Variable"].ToString());
}
}
When the code pasted above runs, it only sees the rows that are pulled in from the database. I think my problem could be fixed by calling something like .databind() somewhere that I'm not, but I've tried a few places and they have not fixed the problem.
Thanks in advance for any help, and helping me become a more robust ASP.NET developer.
When a GridView is DataBind()-ed, the contents of the GridView are "rebuilt" based on the the GridView's DataSource. If you need the new row to stay in the GridView, either do not call DataBind() after the new row is added, or ensure that the contents of your new row are in the GridView's DataSource before future calls to DataBind().
In a page I wrote once I had a similar situation and did the latter. The data for the initial rows was pulled from the database on the first page load and persisted in ViewState. As the user added, removed, and reordered rows in the GridView, the page just changed the data in ViewState and re-DataBind()ed the GridView.

Dynamic Textbox Using Asp.net

in asp.net TextBox will create pressure to button1's. Button2 to the pressure inside the TextBox data consisting of label1 my yazdırıca. I tried to do it like this gives an error.
Object reference not set to an instance of an object.
button1_click{
TextBox txt = new TextBox();
txt.ID = "a";
txt.EnableViewState = true;
Panel1.Controls.Add(txt);
}
Button2_click{
TextBox deneme= Panel1.FindControl("a") as TextBox;
Label1.Text = deneme.Text;
}
After you create your control, on the first click, the control shown on the page and exist.
On the second click the page is not know any more about that text control because you did not save that information somewhere and because only you know that some time in the past you create it.
So on this code you have:
Button2_click{
TextBox deneme= Panel1.FindControl("a") as TextBox;
// here the deneme is null ! and you get the exception !
// the deneme is not exist on the second click, not saved anywhere
Label1.Text = deneme.Text;
}
The solution is to keep on viewstate what control you create and how, and re-create them on PageInit. Alternative you can redesign your page and think a different approach to that, eg you can have the TextControl's all ready on page hidden, and just open them.
Button2_click{
TextBox txt = (TextBox)Panel1.FindControl("a");
Label Label1 = new Label();
Label1.Text=txt.Texxt;
}

Error with dynamically adding controls

I have a UserControl. I dynamically create some controls (Columns for SPGridView. Grid control was added in markup, ObjectDataSource, Button and Label) in CreateChildControl method and add them to Controls collection. Two of these controls are added well (Button and Label) in postback, but one of them (MenuTemplate) raise the exception with such content:
"Failed to load viewstate. The control tree into which viewstate is
being loaded must match the control tree that was used to save
viewstate during the previous request. For example, when adding
controls dynamically, the controls added during a post-back must match
the type and position of the controls added during the initial
request. "
When I move my code to OnInit method all controls are added successfully. So, I have a question: Could someone explain me why some controls are added to Controls collection successfully and others are failed in CreateChildControls in postback? I have read about ViewState here. Probably I didn't understand some moments.
Look at me code:
protected override void CreateChildControls()
{
Label l = new Label();
l.ID = "labelTest";
l.Text = "Hello test!";
Button b = new Button();
b.Text = "Press test";
b.ID = "buttonTest";
b.Click += b_Click;
Controls.Add(l);
Controls.Add(b);
ObjectDataSource gridDataSource = new ObjectDataSource();
gridDataSource.ID = "gridDataSource";
gridDataSource.SelectMethod = "GetDataSource";
gridDataSource.TypeName = this.GetType().AssemblyQualifiedName;
Controls.Add(gridDataSource);
SPMenuField colMenu = new SPMenuField();
colMenu.HeaderText = "Test";
colMenu.TextFields = "Test";
colMenu.MenuTemplateId = "ListMenu";
// it is my SPGridView that added in markup
customGridView.Columns.Add(colMenu);
MenuTemplate titleListMenu = new MenuTemplate();
titleListMenu.ID = "ListMenu";
// The exception occurs here
Controls.Add(titleListMenu);
base.CreateChildControls();
}
I think, you can only add items into a template in Page_Load or other events(ie, after Page_Init) so that it will be retained in postback, not the template itself.. Templates are need to be created before or at Page_Init stage, otherwise it may not load the controls into that templates from viewstate or may result in error.

Issue binding a DataTable to an ASP.Net GridView control

I'm trying to allow my users to enter in large lists of data using an ASP.Net GridView control. The affect I'm trying to create is to make the GridView control act like a spreadsheet. The user can freely enter data and tab from column to column and row to row. The user can use a button at the bottom of the page to add rows as needed. There is also a button at the bottom of the form to save as needed.
To do this, I created a DataTable with a bunch of empty rows and bound it to a GridView. The GridView's columns are template columns that contain textboxes. So, when the page opens, it actually looks like a spread sheet. When the user hits the add rows button, I just add another ten rows to the DataTable the GridView is bound to and it works like a charm.
The issue I'm running into is reading the data that the user entered. When the user hits the paging link or the update button, I would like to update the DataTable with the data the user typed in. Here is what I have.
Private Sub UpdateDataTable()
Dim objCatRow As clsCategoriesRow = Session("gvCategoriesRow")
Dim drQuery() As DataRow = Nothing
Dim drRow As DataRow = Nothing
Dim objRow As GridViewRow = Nothing
Dim intRecNo As Integer = 0
Dim txt As TextBox = Nothing
Dim lbl As Label = Nothing
'Loop through all of the rows in the grid view control
For Each objRow In Me.gvCategories.Rows
'Get the label that contains the identity column
lbl = objRow.Cells(GridColumns.Category).FindControl("lblItemRecNo")
intRecNo = lbl.Text
'Update the datarow bound to this grid view row
'First, query the datarow from the data table
drQuery = objCatRow.Table.Select("recno = " & intRecNo)
'Make sure our query returned a row
If Not IsNothing(drQuery) AndAlso drQuery.Count > 0 Then
'Get the value from the textbox in the grid view
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
'Upadte the data row with the value the user entered
'THE VALUE IN txt.Text IS EMPTY. HOW CAN I GET THE VALUE THE USER TYPED IN?
drQuery(0)("Category") = txt.Text
'Get the value from the textbox in the grid view
txt = objRow.Cells(GridColumns.SortORder).FindControl("txtItemSortOrder")
'Upadte the data row with the value the user entered
drQuery(0)("sortorder") = txt.Text
End If
Next
End Sub
The issue is that this is not returning what the user typed in. The line
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
returns a reference to the textbox in the templated column. But, it contains the previous value, the value from the view state, not the value the user typed in.
How can I get the value the user typed into the grid?
I want to mention that I know how to add EDIT and UPDATE buttons to each row. I would like to avoid doing that way if I can. My users have huge lists of data to enter in and that approach would make the application unusable.
Thanks in advance,
Mike
The form data posted by the user is found in the Page.Request.Form.Item collection. The Page.Request.Form.AllKeys lists the "keys" associated with all of the form item values.
If Page.Request.Form.HasKeys Then
For Each key as String In Page.Request.Form.AllKeys
' step through the keys and use Page.Request.Form.Item(key) to get the data entered
Next
end If
After testing, I was able to get the data from the Request.Form data or the GridView control during page.load on postback, as long as you don't bind the control on postback, but only during the initial request ("GET").
Keep in mind, controls have to be re-created for each request to the page. The Request data posted is used by ASP.NET to repopulate form data controls only after the controls are re-created on the page and the ViewState for the controls is processed, etc.
Request.Form collection
ASP.NET Page Life Cycle
You should replace this:
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory")
with this
txt = objRow.Cells(GridColumns.Category).FindControl("txtItemCategory").Value

storing the value of dynamically created textbox in session

I have done a project in ASP.Net that asks to input a number in textbox. After typing a number in it and click a button it generates the number of textbox according to the value given in the textbox. Like if I type 5 in the textbox it dynamically generates 5 textboxes below.
I want all the value of dynamically created textbox(more than one textbox) to be stored in session and pass to next page through session after clicking another button. But i could not do that.
How can i solve this problem.
Anyone can help me.
Thanks
You could create an array with the values and store that in the session. Code below is untested, but should give you an idea.
string[] arrayTextboxes = new string[numberOfTextboxes];
int index = 0;
foreach (Control ctrl in Page.Controls)
{
if (ctrl is TextBox)
{
arrayTextboxes[index] = ((Textbox)ctrl).Text;
index++;
}
}
Session["tbValues"] = arrayTextboxes;

Resources