Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Adding controls at runtime 2

Status
Not open for further replies.

PsychoCoder

Programmer
May 31, 2006
140
US
In my application I have a page where I need to add textboxes if the user clicks a linkbutton, below is the sub I have written to add the textboxes:

Code:
Protected Sub net_add_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles net_add.Click
		Dim new_item As New Literal
		new_item.Text = "<tr>" & vbCrLf
		new_item.Text &= "<td style=""WIDTH: 145px;          HEIGHT: 61px"" valign=""top"">" & vbCrLf
		new_item.Text &= "<ASP:TEXTBOX ID=""object_2"" RUNAT=""server"" WIDTH=""145px"" />" & vbCrLf
		new_item.Text &= "</td>"
		new_item.Text &= "<td style=""WIDTH: 506px; HEIGHT: 61px"">" & vbCrLf
		new_item.Text &= "<ASP:TEXTBOX ID=""changes_2"" RUNAT=""server"" WIDTH=""459px"" HEIGHT=""53px""         TEXTMODE=""MultiLine""/>" & vbCrLf
		new_item.Text &= "</td>" & vbCrLf
		new_item.Text &= "</tr>"
		Me.net_xtras.Controls.Add(new_item)
End Sub

When I click the linkbutton nothing shows (though the area increases in size as it would if new items were there. If I right click and view the source I can see the text for the new items yet they dont show in the page. Anyone have any ideas?

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code Gremlins Must Go Down Hard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
A better way to handle this would be to create individual objects and add the textboex etc, to the table cell, then add the tablerow then add the table to the page.
 
jbenson001,

Thanks for the advice, I changed the click sub for that linkbutton to add controls:

Code:
Dim new_table As New Table
		Dim tr As New TableRow
		Dim td As New TableCell
		Dim td2 As New TableCell
		Dim txt1 As New TextBox
		Dim txt2 As New TextBox

		With new_table
			.ID = "new_controls"
			.CellPadding = 2
			.CellSpacing = 2
			.Width = 829
		End With
		With tr
			.VerticalAlign = VerticalAlign.Top
		End With
		With td
			.Width = 200
			.Height = 61
			.VerticalAlign = VerticalAlign.Top
		End With
		With td2
			'.Width = 600
			.Height = 61
		End With
		With txt1
			.ID = "object_" & ViewState("NetCounter") + 2
			.Width = 145
			.CssClass = "api_controls"
		End With
		With txt2
			.ID = "changes_" & ViewState("NetCounter") + 2
			.TextMode = TextBoxMode.MultiLine
			.Width = 459
			.Height = 53
			.CssClass = "api_tkt_area"
		End With
		tr.Controls.Add(td)
		tr.Controls.Add(td2)
		td.Controls.Add(txt1)
		td2.Controls.Add(txt2)
		new_table.Controls.Add(tr)
		net_xtras.Controls.Add(new_table)
		ViewState("NetCounter") = ViewState("NetCounter") + 1
		Response.Write(ViewState("NetCounter"))
		tr = Nothing
		td = Nothing
		td2 = Nothing
		txt1 = Nothing
		txt2 = Nothing
		new_table = Nothing

I have the Response.Write(ViewState("NetCounter")) part in there just ofr me, so I can amke sure the coutner is incrementing as its supposed to( and it is), the problem Im having is no matter how many times you click the "Add" link I only have one extra set of controls, not multiple as should be.

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code Gremlins Must Go Down Hard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
you need to set up another variable to keep track of how many controls you have because with each postback you must recreate all programmatically created controls.

ie you hit add 1 time, checking control variable count, its at 0 right now, so set variable to 2, loop through control creation code.

hit add button again. retrieve control creation variable. value is currently 2, add 2 more to it, then do your loop to create. etcetc.
 
tperri,

Thanks for the help, Ive got that working now but Im losing the text typed into the generated textboxes. I know they have to be regerated on each postback and Ive been trying to save that text into a ViewState object but its not working. Below is the code Im using:

Code:
Protected Sub net_add_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles net_add.Click
		
		Dim iCount As Integer
		iCount = 0

		Do While iCount <= ViewState("NetCounter")
			Dim new_table As New Table
			Dim tr As New TableRow
			Dim td As New TableCell
			Dim td2 As New TableCell
			Dim txt1 As New TextBox
			Dim txt2 As New TextBox
			If Not CType(Me.FindControl("object_" & iCount), TextBox) Is Nothing Then
				ViewState("object_" & iCount) = CType(Me.FindControl("object_" & iCount), TextBox).Text
			Else
				ViewState("object_" & iCount) = String.Empty
			End If

			If Not CType(Me.FindControl("changes_" & iCount), TextBox) Is Nothing Then
				ViewState("changes_" & iCount) = CType(Me.FindControl("changes_" & iCount), TextBox).Text
			Else
				ViewState("changes_" & iCount) = String.Empty
			End If
			With new_table
				.ID = "new_controls_" & iCount + 2
				.CellPadding = 2
				.CellSpacing = 2
				.Width = 829
			End With
			With tr
				.VerticalAlign = VerticalAlign.Top
			End With
			With td
				.Width = 200
				.Height = 61
				.VerticalAlign = VerticalAlign.Top
			End With
			With td2
				'.Width = 600
				.Height = 61
			End With
			With txt1
				.ID = "object_" & iCount + 2
				.Width = 145
				.CssClass = "api_controls"
				.Text = ViewState("object_" & iCount)
			End With
			With txt2
				.ID = "changes_" & iCount + 2
				.TextMode = TextBoxMode.MultiLine
				.Width = 459
				.Height = 53
				.CssClass = "api_tkt_area"
				.Text = ViewState("changes_" & iCount)
			End With
			tr.Controls.Add(td)
			tr.Controls.Add(td2)
			td.Controls.Add(txt1)
			td2.Controls.Add(txt2)
			new_table.Controls.Add(tr)
			net_xtras.Controls.Add(new_table)

			iCount += 1
			tr = Nothing
			td = Nothing
			td2 = Nothing
			txt1 = Nothing
			txt2 = Nothing
			new_table = Nothing
		Loop
		If Not ViewState("NetCounter") Is Nothing Then
			ViewState("NetCounter") += 1
		End If
	End Sub

The generation of textboxes works great, can you help me figure out why the text isnt being retained?

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code Gremlins Must Go Down Hard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
here is part of my code in a submit onclick event where i get my textbox values. you must create textbox controls to get their values - you canty refernce them by name.

sorry this is in C# but you'll get the idea

Code:
    protected void cmdSumbit_Click(object sender, ImageClickEventArgs e)
    {
        // get dynamic textbox for phonenumbers values
        int n = Int32.Parse(Session["NumberOfPhones"].ToString());
        string[] strPhoneValues = new string[n];
        string[] strPhoneIDValues = new string[n];
        

        for (int x = 0; x < n; x++)
        {
            string boxName = "txtPhoneNumber" + (x + 1);
            string idboxName = "txtPhoneID" + (x + 1);
            strPhoneValues[x] = ((TextBox)FindControl(boxName)).Text;
            strPhoneIDValues[x] = ((TextBox)FindControl(idboxName)).Text;
        }

        // get dynamic textbox values

        DataSet ds = DatabaseFunctions.GetOrgItems(Convert.ToInt32(Session["SiteID"]), "OrganizationData");
        int i = Int32.Parse(ds.Tables[0].Rows.Count.ToString());
        string[] strFieldName = new string[i];
        string[] strFieldNameValues = new string[i];
        int y = 0;
        foreach(DataRow dr in ds.Tables[0].Rows)
        {
            string strfieldName = dr["fieldname"].ToString();
            string strfieldNameValues = "txt" + dr["fieldname"].ToString();
            strFieldName[y] = strfieldName;
            strFieldNameValues[y] = ((TextBox)FindControl(strfieldNameValues)).Text;
            y++;
        }

........
 
Heres what Im up against, the user has the option of clicking a link to add 2 textboxes dynamically (at anytime during the process) when they click the link the text in the current dynamic boxes are lost, I tried using the below sub procedure to store the text in a viewstate object:

Code:
Protected Sub net_add_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles net_add.Click
		Dim n As Integer = Int32.Parse(ViewState("NetCounter"))
		Response.Write(n)
		'Response.End()
		Dim iCount As Integer
		iCount = 0
		Dim txtValue(n) As String
		Dim txtValue2(n) As String
		Do While iCount <= ViewState("NetCounter") + 1
			Dim i As Integer = iCount + 2
			Dim box_name As String
			Dim box_name2 As String
			Dim new_table As New Table
			Dim tr As New TableRow
			Dim td As New TableCell
			Dim td2 As New TableCell
			Dim txt1 As New TextBox
			Dim txt2 As New TextBox
			box_name = "object_" & (i)
			box_name2 = "changes_" & (i)

			If Not box_name Is Nothing Then
				txtValue(n) = CType(FindControl(box_name), TextBox).Text
			Else
				txtValue(n) = String.Empty
			End If
			If Not box_name2 Is Nothing Then
				txtValue2(n) = CType(FindControl(box_name2), TextBox).Text
			Else
				txtValue2(n) = String.Empty
			End If

			ViewState("Text1") = txtValue(n).ToString
			ViewState("Text2") = txtValue2(n).ToString

			With new_table
				.ID = "new_controls_" & i
				.CellPadding = 2
				.CellSpacing = 2
				.Width = 829
			End With
			With tr
				.VerticalAlign = VerticalAlign.Top
			End With
			With td
				.Width = 200
				.Height = 61
				.VerticalAlign = VerticalAlign.Top
			End With
			With td2
				'.Width = 600
				.Height = 61
			End With
			With txt1
				.ID = "object_" & i
				.Width = 145
				.CssClass = "api_controls"
				.Text = ViewState("Text1")
			End With
			With txt2
				.ID = "changes_" & i
				.TextMode = TextBoxMode.MultiLine
				.Width = 459
				.Height = 53
				.CssClass = "api_tkt_area"
				.Text = ViewState("Text2")
			End With
			tr.Controls.Add(td)
			tr.Controls.Add(td2)
			td.Controls.Add(txt1)
			td2.Controls.Add(txt2)
			new_table.Controls.Add(tr)
			net_xtras.Controls.Add(new_table)

			iCount += 1
			tr = Nothing
			td = Nothing
			td2 = Nothing
			txt1 = Nothing
			txt2 = Nothing
			new_table = Nothing
			ViewState("Text1") = String.Empty
			ViewState("Text2") = String.Empty
		Loop
		If Not ViewState("NetCounter") Is Nothing Then
			ViewState("NetCounter") += 1
		End If
	End Sub

but when the link is clicked to add another set of textboxes I get a Exception Details: System.NullReferenceException: Object reference not set to an instance of an object. error. Can anyone help me wiht this?

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code Gremlins Must Go Down Hard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
tperri,

The bold line is where I get the error:

Code:
Protected Sub net_add_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles net_add.Click
        Dim n As Integer = Int32.Parse(ViewState("NetCounter"))
        Response.Write(n)
        'Response.End()
        Dim iCount As Integer
        iCount = 0
        Dim txtValue(n) As String
        Dim txtValue2(n) As String
        Do While iCount <= ViewState("NetCounter") + 1
            Dim i As Integer = iCount + 2
            Dim box_name As String
            Dim box_name2 As String
            Dim new_table As New Table
            Dim tr As New TableRow
            Dim td As New TableCell
            Dim td2 As New TableCell
            Dim txt1 As New TextBox
            Dim txt2 As New TextBox
            box_name = "object_" & (i)
            box_name2 = "changes_" & (i)

            If Not box_name Is Nothing Then
                [b]txtValue(n) = CType(FindControl(box_name), TextBox).Text[/b]
            Else
                txtValue(n) = String.Empty
            End If
            If Not box_name2 Is Nothing Then
                txtValue2(n) = CType(FindControl(box_name2), TextBox).Text
            Else
                txtValue2(n) = String.Empty
            End If

            ViewState("Text1") = txtValue(n).ToString
            ViewState("Text2") = txtValue2(n).ToString

            With new_table
                .ID = "new_controls_" & i
                .CellPadding = 2
                .CellSpacing = 2
                .Width = 829
            End With
            With tr
                .VerticalAlign = VerticalAlign.Top
            End With
            With td
                .Width = 200
                .Height = 61
                .VerticalAlign = VerticalAlign.Top
            End With
            With td2
                '.Width = 600
                .Height = 61
            End With
            With txt1
                .ID = "object_" & i
                .Width = 145
                .CssClass = "api_controls"
                .Text = ViewState("Text1")
            End With
            With txt2
                .ID = "changes_" & i
                .TextMode = TextBoxMode.MultiLine
                .Width = 459
                .Height = 53
                .CssClass = "api_tkt_area"
                .Text = ViewState("Text2")
            End With
            tr.Controls.Add(td)
            tr.Controls.Add(td2)
            td.Controls.Add(txt1)
            td2.Controls.Add(txt2)
            new_table.Controls.Add(tr)
            net_xtras.Controls.Add(new_table)

            iCount += 1
            tr = Nothing
            td = Nothing
            td2 = Nothing
            txt1 = Nothing
            txt2 = Nothing
            new_table = Nothing
            ViewState("Text1") = String.Empty
            ViewState("Text2") = String.Empty
        Loop
        If Not ViewState("NetCounter") Is Nothing Then
            ViewState("NetCounter") += 1
        End If
    End Sub

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code Gremlins Must Go Down Hard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Of course the problem is that controls created at runtime have to be recreated each postback and won't maintain viewstate unless they're recreated in [tt]Page_Init[/tt] So here's the solution
Code:
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
    InitializeComponent()

    Dim myTextbox As TextBox
    Dim myRow As TableRow
    Dim myCell As TableCell

    If Not IsPostBack Then Session("TextBoxCount") = -1
    For counter As Integer = 0 To Session("TextBoxCount")
        createTextBox(counter)
    Next
End Sub

Private Sub myButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles myButton.Click
    Session("TextBoxCount") += 1
    createTextBox(Session("TextBoxCount"))
End Sub

Private Function createTextBox(ByVal iIndex)
    Dim myTextbox As TextBox
    Dim myRow As TableRow
    Dim myCell As TableCell

    myTextbox = New TextBox
    myTextbox.ID = "txtMine" & iIndex
    myCell = New TableCell
    myCell.Controls.Add(myTextbox)
    myRow = New TableRow
    myRow.Cells.Add(myCell)
    myTable.Rows.Add(myRow)
End Function
Now your textboxes are created before viewstate is applied to the controls so you can let Microsoft handle it. Let me know if this works out for you. Thanks, and have a great day.
 
jonbatts,

Thank you SO much, this works perfectly!

Senior Qik III,.Net,SQL Programmer

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** Do NOT feed Code Gremlins after midnight **
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top