Solved

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

Posted on 2010-11-24
13
619 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
Comment Utility
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
Comment Utility
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
Comment Utility
What event would I use to save the table? It seems like any event that causes postback wipes out the table.
0
 
LVL 21

Expert Comment

by:Alfred1
Comment Utility
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
Comment Utility
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
Comment Utility
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 29

Expert Comment

by:Kumaraswamy R
Comment Utility
0
 

Author Comment

by:AmyL
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
That worked - thanks!
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

A quick way to get a menu to work on our website, is using the Menu control and assign it to a web.sitemap using SiteMapDataSource. Example of web.sitemap file: (CODE) Sample code to add to the page menu: (CODE) Running the application, we wi…
Problem Hi all,    While many today have fast Internet connection, there are many still who do not, or are connecting through devices with a slower connect, so light web pages and fast load times are still popular.    If your ASP.NET page …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

772 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now