Solved

How to get values from text boxes in a dynamically created table?

Posted on 2010-11-24
13
624 Views
Last Modified: 2012-05-10
I need to create a table dynamically on an asp.net page. The row count and column count will be determined by the users.

I found some code that works for creating the table and populating it with text boxes. The problem is that I need to gather the values of text boxes on a button click, however I am not sure how to get these values. The code is attached.

Thanks!
Amy
' Rows property to hold the Rows in the ViewState
    Protected Property Rows() As Integer
        Get
            If Not ViewState("Rows") Is Nothing Then
                Return CInt(Fix(ViewState("Rows")))
            Else
                Return 0
            End If
        End Get
        Set(ByVal value As Integer)
            ViewState("Rows") = value
        End Set
    End Property

    ' Columns property to hold the Columns in the ViewState
    Protected Property Columns() As Integer
        Get
            If Not ViewState("Columns") Is Nothing Then
                Return CInt(Fix(ViewState("Columns")))
            Else
                Return 0
            End If
        End Get
        Set(ByVal value As Integer)
            ViewState("Columns") = value
        End Set
    End Property

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' Run only once a postback has occured
        If Page.IsPostBack Then
            'Set the Rows and Columns property with the value
            'entered by the user in the respective textboxes
            Me.Rows = Int32.Parse(txtRows.Text)
            Me.Columns = Int32.Parse(txtCols.Text)
        End If
        CreateDynamicTable()
    End Sub

    Private Sub CreateDynamicTable()
        PlaceHolder1.Controls.Clear()

        ' Fetch the number of Rows and Columns for the table 
        ' using the properties
        Dim tblRows As Integer = Rows
        Dim tblCols As Integer = Columns
        ' Create a Table and set its properties 
        Dim tbl As Table = New Table()
        ' Add the table to the placeholder control
        PlaceHolder1.Controls.Add(tbl)
        ' Now iterate through the table and add your controls 
        For i As Integer = 0 To tblRows - 1
            Dim tr As TableRow = New TableRow()
            For j As Integer = 0 To tblCols - 1
                Dim tc As TableCell = New TableCell()
                Dim txtBox As TextBox = New TextBox()
                'txtBox.Text = "RowNo:" & i & " " & "ColumnNo:" & " " & j
                ' Add the control to the TableCell
                tc.Controls.Add(txtBox)
                ' Add the TableCell to the TableRow
                tr.Cells.Add(tc)
            Next j
            ' Add the TableRow to the Table
            tbl.Rows.Add(tr)
        Next i

        ' This parameter helps determine in the LoadViewState event,
        ' whether to recreate the dynamic controls or not

        ViewState("dynamictable") = True
    End Sub

    Protected Sub btnGenerate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGenerate.Click
        CreateDynamicTable()
    End Sub

    ' Check the ViewState flag to determine whether to 
    ' rebuild your table again
    Protected Overrides Sub LoadViewState(ByVal earlierState As Object)
        MyBase.LoadViewState(earlierState)
        If ViewState("dynamictable") Is Nothing Then
            CreateDynamicTable()
        End If
    End Sub

    Protected Sub btnView_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnView.Click
        Dim tblRows As Integer = 3
        Dim tblCols As Integer = 3
        Dim tbl As Table = DirectCast(PlaceHolder1.Controls(0), Table)


        For i As Integer = 0 To tblRows - 1
            Dim tr As TableRow
            For j As Integer = 0 To tblCols - 1
                Dim tc As TableCell
                Dim txtBox As TextBox

                tr = tbl.Rows(i)
                tc = tbl.Rows(i).Cells(j)
                txtBox = DirectCast(tc.Controls(0), TextBox)
                txtValues.Text &= " " & txtBox.Text

                ' Add the control to the TableCell
                'tc.Controls.Add(txtBox)
                ' Add the TableCell to the TableRow
                'tr.Cells.Add(tc)
            Next j
            ' Add the TableRow to the Table
            'tbl.Rows.Add(tr)
        Next i

Open in new window

0
Comment
Question by:AmyL
  • 5
  • 5
  • 2
  • +1
13 Comments
 
LVL 21

Expert Comment

by:Alfred1
ID: 34210389
Try using Sessions to store any changes in your dynamic table and at a time when you need to retrieve the values.

To store after an action, for example:

Session("CurrentDynamicTable") = tbl

To retrieve current dynamic table state.

Dim tbl As Table = CType(Session("CurrentDynamicTable"),Table)
0
 
LVL 21

Expert Comment

by:Alfred1
ID: 34210410
Oh by the way, in retrieving the values after retrieving the current table from a Session variable, you can access it something like this.

Dim tbl As New Table
Dim testVal As String

For I As Integer = 0 To tbl.Rows.Count - 1
            For J As Integer = 0 To tbl.Rows(I).Cells.Count - 1
                testVal = tbl.Rows(I).Cells(J).Text
            Next
Next
0
 

Author Comment

by:AmyL
ID: 34210451
What event would I use to save the table? It seems like any event that causes postback wipes out the table.
0
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 
LVL 21

Expert Comment

by:Alfred1
ID: 34210465
That would depend on what you are trying to do.  For example, if you are displaying the table values in the page, you can try store the table values in a Session variable first before displaying it.

Afterwards, when you for example press a button, you can then retrieve the current table through the Session variable.
0
 

Author Comment

by:AmyL
ID: 34210478
Ultimately, I am trying to update a database table with the values in the text boxes, but for the example, I would be happy with displaying values in the text box 'txtView'.
0
 
LVL 21

Expert Comment

by:Alfred1
ID: 34210563
As I said in my previous post, store your dynamic table in a Session variable after doing something with it.

Session("CurrentDynamicTable") = tbl  //tbl had been populated or manipulated before

And then display it in your textbox, something like this in an event somewhere

Dim tbl As Table = CType(Session("CurrentDynamicTable"),Table)

For I As Integer = 0 To tbl.Rows.Count - 1
            For J As Integer = 0 To tbl.Rows(I).Cells.Count - 1
               txtView.text = txtView.text & tbl.Rows(I).Cells(J).Text & vbCrLf
            Next
Next
0
 
LVL 29

Expert Comment

by:Kumaraswamy R
ID: 34210564
0
 

Author Comment

by:AmyL
ID: 34210596
What I don't understand is which event to put any code in, because on postback my table no longer exists. I actually have code that can retrieve the values, but I don't know which event will fire without losing my table.
0
 
LVL 21

Expert Comment

by:Alfred1
ID: 34210617
Check this out:

http://msdn.microsoft.com/en-us/library/ms178581.aspx

Store your current table in an event where your table still exists in a Session variable.

And then you can retrieve the values later through this Session variable.  Note that HTTP is a stateless protocol and that is why upon postback your table no longer exists.

Please review the overview in the provided link.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 34212742
In my example below I'm creating the table dynamically, when a button is clicked.  That button is calling a CreateDynamicTable method I wrote, and also storing the table's ID and row & column counts in Session variables.

On Page_Load I check If Session("DynamicTable") IsNot Nothing, and if that session variable has been previously set I call the same CreateDynamicTable method.  That method gives the text boxes in the cell an ID using the row and column number, so every time I call CreateDynamicTable the text boxes have the same ID's - and so long as they have the same ID's the ViewState should be persisted for you.

To retrieve the values of the text boxes I used a simple sub that recursively checks every control in the table, and if it's a TextBox adds it to a List(Of TextBox)

Markup:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" 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">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
		<div id="tablePlaceHolder" runat="server">
		</div>
		<hr />
		Rows: <asp:TextBox ID="RowCountTextBox" runat="server" /><br />
		Columns: <asp:TextBox ID="ColCountTextBox" runat="server" /><br />
		<asp:Button ID="CreateTableButton" runat="server" Text="Create Table" /><br />
		<asp:Button ID="GetTextBoxValues" runat="server" Text="Get Text Box Contents" /><br />
		<asp:Button ID="EmptyPostBackButton" runat="server" Text="Cause Postback" />
		<hr />
		<div id="textBoxContentsPlaceHolder" runat="server">
		</div>
    </form>
</body>
</html>

Open in new window



Code behind:
Imports System.Collections.Generic
Partial Class _Default
	Inherits System.Web.UI.Page

	Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit
		If Session("DynamicTable") IsNot Nothing Then
			Dim rows As Integer = Session("DynamicTableRowCount")
			Dim cols As Integer = Session("DynamicTableColCount")
			Dim tblId As String = Session("DynamicTable")

			tablePlaceHolder.Controls.Add(CreateDynamicTable(tblId, rows, cols))
		End If
	End Sub

	Protected Sub CreateTableButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles CreateTableButton.Click
		Dim rowCount As Integer = Int32.Parse(RowCountTextBox.Text)
		Dim colCount As Integer = Int32.Parse(ColCountTextBox.Text)

		Dim dynamicTableId = "DynamicTable"

		tablePlaceHolder.Controls.Add(CreateDynamicTable(dynamicTableId, rowCount, colCount))

		Session("DynamicTableRowCount") = rowCount
		Session("DynamicTableColCount") = colCount
		Session("DynamicTable") = dynamicTableId
	End Sub

	Private Function CreateDynamicTable(ByVal tableId As String, ByVal rowCount As Integer, ByVal columnCount As Integer) As Table
		Dim tbl As New Table()
		tbl.ID = tableId
		For i As Integer = 0 To rowCount - 1
			Dim row As New TableRow()
			For j As Integer = 0 To columnCount - 1
				Dim cell As New TableCell()
				Dim tb As New TextBox()
				tb.ID = "DynamicTextBox" & i.ToString() & j.ToString()
				cell.Controls.Add(tb)
				row.Cells.Add(cell)
			Next
			tbl.Rows.Add(row)
		Next
		Return tbl
	End Function

	Private Sub GetTextBoxes(ByVal ParentControl As Control, ByVal TextBoxList As List(Of TextBox))
		For Each ctl As Control In ParentControl.Controls
			If ctl.HasControls() Then
				GetTextBoxes(ctl, TextBoxList)
			End If
			If TypeOf ctl Is TextBox Then
				TextBoxList.Add(ctl)
			End If
		Next
	End Sub

	Protected Sub GetTextBoxValues_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles GetTextBoxValues.Click
		Dim results As New StringBuilder()
		Dim textBoxes As New List(Of TextBox)
		GetTextBoxes(FindControl(Session("DynamicTable")), textBoxes)
		For Each tb As TextBox In textBoxes
			results.AppendFormat("Text box id: <i>{0}</i>, contents: <i>{1}</i><br />{2}", tb.ID, tb.Text, Environment.NewLine)
		Next
		textBoxContentsPlaceHolder.InnerHtml = results.ToString()
	End Sub
End Class

Open in new window

0
 

Author Comment

by:AmyL
ID: 34213058
Hi!

I tried this code, but I ran into the same problem I have with mine. Clicking the 'Get Values' button caused the object to no longer exist, and I got an object reference error on this line:

For Each ctl As Control In ParentControl.Controls


Does it work for you?

Thanks!
Amy
0
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 500 total points
ID: 34213191
Yes, it does.  Bear in mind that the GetTextBoxes() method needs the ID of a control on the page where it starts the search for text boxes.  GetTextBoxes() searches all the children of the ParentControl parameter, finding text boxes and adding them to a list.  Your error would indicate GetTextBoxes() is not receiving a valid control for the ParentControl parameter - if you copied my example it's probably because FindControl() isn't finding the ID specified.

When I create the table I also assign it an ID, and store that ID in a Session variable.  When the "get results" button is clicked I use FindControl() with the table ID I previously stored in the Session, and pass whatever FindControl() finds to GetTextBoxes().

Make sure you're passing a valid control to the GetTextBoxes() method (I passed the table itself in my example - but my HTML also includes a <div runat="server"> that wraps the table, so I could use that as well).

Here's a slightly modified example that passes the DIV to GetTextBoxes() (try copying this in it's entirety, unmodified, into a new page and step through to get an idea what it's doing):
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Collections.Generic" %>

<!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 id="Head1" runat="server">
    <title></title>
	<script runat="server">
		Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
			If IsPostBack Then
				If Session("DynamicTable") IsNot Nothing Then
					Dim rows As Integer = Session("DynamicTableRowCount")
					Dim cols As Integer = Session("DynamicTableColCount")
					Dim tblId As String = Session("DynamicTable")

					tablePlaceHolder.Controls.Add(CreateDynamicTable(tblId, rows, cols))
				End If
			End If
		End Sub

		Protected Sub CreateTableButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles CreateTableButton.Click
			Dim rowCount As Integer = Int32.Parse(RowCountTextBox.Text)
			Dim colCount As Integer = Int32.Parse(ColCountTextBox.Text)

			Dim dynamicTableId = "DynamicTable"

			tablePlaceHolder.Controls.Add(CreateDynamicTable(dynamicTableId, rowCount, colCount))

			Session("DynamicTableRowCount") = rowCount
			Session("DynamicTableColCount") = colCount
			Session("DynamicTable") = dynamicTableId
		End Sub

		Private Function CreateDynamicTable(ByVal tableId As String, ByVal rowCount As Integer, ByVal columnCount As Integer) As Table
			Dim tbl As New Table()
			tbl.ID = tableId
			For i As Integer = 0 To rowCount - 1
				Dim row As New TableRow()
				For j As Integer = 0 To columnCount - 1
					Dim cell As New TableCell()
					Dim tb As New TextBox()
					tb.ID = "DynamicTextBox" & i.ToString() & j.ToString()
					cell.Controls.Add(tb)
					row.Cells.Add(cell)
				Next
				tbl.Rows.Add(row)
			Next
			Return tbl
		End Function

		Private Sub GetTextBoxes(ByVal ParentControl As Control, ByVal TextBoxList As List(Of TextBox))
			If ParentControl Is Nothing Then
				Throw New ArgumentException("A valid control to search for text boxes must be specified.", "ParentControl")
			End If
			If TextBoxList Is Nothing Then
				Throw New ArgumentException("TextBoxList must be initialized prior to calling GetTextBoxes().", "TextBoxList")
			End If
			For Each ctl As Control In ParentControl.Controls
				If ctl.HasControls() Then
					GetTextBoxes(ctl, TextBoxList)
				End If
				If TypeOf ctl Is TextBox Then
					TextBoxList.Add(ctl)
				End If
			Next
		End Sub

		Protected Sub GetTextBoxValues_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles GetTextBoxValues.Click
			Dim results As New StringBuilder()
			
			'Initialize an empty list of text boxes to pass into GetTextBoxes
			'When GetTextBoxes() returns this list will contain every text
			'box contained in tablePlaceHolder or any of it's children
			Dim textBoxes As New List(Of TextBox)
			GetTextBoxes(tablePlaceHolder, textBoxes)
			
			For Each tb As TextBox In textBoxes
				results.AppendFormat("Text box id: <i>{0}</i>, contents: <i>{1}</i><br />{2}", tb.ID, tb.Text, Environment.NewLine)
			Next
			textBoxContentsPlaceHolder.InnerHtml = results.ToString()
		End Sub
	</script>
</head>
<body>
    <form id="form1" runat="server">
		<div id="tablePlaceHolder" runat="server">
		</div>
		<hr />
		Rows: <asp:TextBox ID="RowCountTextBox" runat="server" /><br />
		Columns: <asp:TextBox ID="ColCountTextBox" runat="server" /><br />
		<asp:Button ID="CreateTableButton" runat="server" Text="Create Table" /><br />
		<asp:Button ID="GetTextBoxValues" runat="server" Text="Get Text Box Contents" /><br />
		<asp:Button ID="EmptyPostBackButton" runat="server" Text="Cause Postback" />
		<hr />
		<div id="textBoxContentsPlaceHolder" runat="server">
		</div>
    </form>
</body>
</html>

Open in new window

tgerbert-373629.flv
0
 

Author Closing Comment

by:AmyL
ID: 34213258
That worked - thanks!
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

User art_snob (http://www.experts-exchange.com/M_6114203.html) encountered strange behavior of Android Web browser on his Mobile Web site. It took a while to find the true cause. It happens so, that the Android Web browser (at least up to OS ver. 2.…
Introduction This article shows how to use the open source plupload control to upload multiple images. The images are resized on the client side before uploading and the upload is done in chunks. Background I had to provide a way for user…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question