Geeks With Blogs

News

Microsoft MVP


DZone MVB


Moderator at CodeASP.NET


Quiz Master







free counters
Free counters
Added on January 19,2012


Follow Me @vmsdurano

A bit About Me



Disclaimer
The opinions expressed herein are my own personal opinions and does not represent the opinions of my employers. Nor does it represent the opinion of my dog, because I don’t have one.


Vinz' Blog (ProudMonkey) "Code, Beer and Music ~ my way of being a programmer"

In my previous post here, I wrote an example that demonstrates how are we going to generate table rows dynamically using ASP Table on click of the Button control. Now based on some comments in my previous example and in the forums they wanted to implement it within Masterpage. Unfortunately the code in my previous example doesn't work in Masterpage for the following main reasons:

  • The Table is dynamically added within the Form tag and so the TextBox control will not be generated correcty in the page.
  • The data will not be retained on each and every postbacks because the SetPreviousData() method is looking for the Table element within the Page and not on the MasterPage.
  • The Request.Form key value should be set correctly since all controls within the master page are prefixed with the naming containter ID to prevent duplicate ids on the final rendered HTML. For example the TextBox control with the ID of TextBoxRow will turn to ID to this ctl00$MainBody$TextBoxRow.

In order for the previous example to work within Masterpage then we will have to correct those three main reasons above and this post will guide you how to correct it.

Suppose we have this content page declaration below:

 

<asp:Content ID="Content1" ContentPlaceHolderID="MainHead" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainBody" Runat="Server">
    <asp:PlaceHolder ID="PlaceHolder1" runat="server">
        <asp:Button ID="BTNAdd" runat="server" Text="Add New Row" OnClick="BTNAdd_Click" />
    </asp:PlaceHolder>
</asp:Content>   

As you notice I've added a PlaceHolder control within the MainBody ContentPlaceHolder. This is because we are going to generate the Table in the PlaceHolder instead of generating it within the Form element. Now since issue #1 is already corrected then let's proceed to the code beind part. Here are the full code blocks below:

 

 

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class DynamicControlDemo : System.Web.UI.Page
{
 
    private int numOfRows = 1;
    protected void Page_Load(object sender, EventArgs e) {
        //Generate the Rows on Initial Load
        if (!Page.IsPostBack) {
            GenerateTable(numOfRows);
        }
    }

    protected void BTNAdd_Click(object sender, EventArgs e) {
        if (ViewState["RowsCount"] != null) {
            numOfRows = Convert.ToInt32(ViewState["RowsCount"].ToString());
            GenerateTable(numOfRows);
        }
    }

    private void SetPreviousData(int rowsCount, int colsCount) {
        Table table = (Table)this.Page.Master.FindControl("MainBody").FindControl("Table1"); // ****         if (table != null) {
            for (int i = 0; i < rowsCount; i++) {
                for (int j = 0; j < colsCount; j++) {
                    //Extracting the Dynamic Controls from the Table
                    TextBox tb = (TextBox)table.Rows[i].Cells[j].FindControl("TextBoxRow_" + i + "Col_" + j);
                    //Use Request object for getting the previous data of the dynamic textbox
                    tb.Text = Request.Form["ctl00$MainBody$TextBoxRow_" + i + "Col_" + j];//*****                 }
            }
        }
    }

    private void GenerateTable(int rowsCount) {
        //Creat the Table and Add it to the Page

        Table table = new Table();
        table.ID = "Table1";
        PlaceHolder1.Controls.Add(table);//******         //The number of Columns to be generated

        const int colsCount = 3;//You can changed the value of 3 based on you requirements
        // Now iterate through the table and add your controls

        for (int i = 0; i < rowsCount; i++) {
            TableRow row = new TableRow();
            for (int j = 0; j < colsCount; j++) {
                TableCell cell = new TableCell();
                TextBox tb = new TextBox();
                // Set a unique ID for each TextBox added

                tb.ID = "TextBoxRow_" + i + "Col_" + j;
                // Add the control to the TableCell
                cell.Controls.Add(tb);
                // Add the TableCell to the TableRow
                row.Cells.Add(cell);
            }
            // And finally, add the TableRow to the Table
            table.Rows.Add(row);
        }

        //Set Previous Data on PostBacks
        SetPreviousData(rowsCount, colsCount);
        //Sore the current Rows Count in ViewState
        rowsCount++;
        ViewState["RowsCount"] = rowsCount;
    }
}

 

As you observed the code is pretty much similar to the previous example except for the highlighted lines above.

That's it! I hope someone find this post usefu!

Posted on Friday, December 3, 2010 8:35 PM ASP.NET , C# | Back to top


Comments on this post: Master Page: Dynamically Adding Rows in ASP Table on Button Click event

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
I am trying to convert your example to VB but get erros in the set previous data proc when it tries to find the control for TextBoxRow.

Her is how I converted:

Protected Sub SetPreviousData(ByVal rowsCount as Integer,byVal colsCount as integer)
Dim rowCtr as integer = 0
Dim colCtr as integer = 0
Dim tbl as Table = Me.Page.Master.FIndControl(“MainContent”).FIndControl(“Table1”)
If tbl isnot nothing
For rowCtr = 0 to rowsCount
For colCtr = 0 to colsCount
Dim tb as TextBox = tbl.rows(rowCtr).Cells(colCtr).findcontrol(“TextBoxRow_” & rowCtr & “Col_” & colCtr)
tb.Text = Request.Form(“ctl00$MainContent$TextBoxRow_” & rowCtr & “Col_” & colCtr)
next
next
End if


End Sub
Left by Eric on Apr 26, 2011 10:37 PM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
@Eric,

What's the actual error you are getting? can you post it here?
Left by Vinz on Apr 26, 2011 11:17 PM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
Here is the latest if statement:
If tbl IsNot Nothing Then
For rowCtr = 0 To rowsCount
For colCtr = 0 To colsCount
Dim tb As TextBox = CType(tbl.Rows(rowCtr).Cells(colCtr).FindControl("TextBoxRow_" & rowCtr & "Col_" & colCtr), TextBox)
Dim temptb As Object = tb
If Not (temptb = Nothing) Then
tb.Text = Request.Form("ctl00$MainContent$TextBoxRow_" & rowCtr & "Col_" & colCtr)
End If
Next
Next
End If

And here is the error:
Specified argument was out of the range of valid values.
Parameter name: index
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index

Source Error:


Line 48: For rowCtr = 0 To rowsCount
Line 49: For colCtr = 0 To colsCount
Line 50: Dim tb As TextBox = CType(tbl.Rows(rowCtr).Cells(colCtr).FindControl("TextBoxRow_" & rowCtr & "Col_" & colCtr), TextBox)
Line 51: Dim temptb As Object = tb
Line 52: If Not (temptb = Nothing) Then


Source File: C:\Users\ELindquist\Documents\Visual Studio 2010\WebSites\WebSite7\Default.aspx.vb Line: 50

Stack Trace:


[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index]
System.Web.UI.ControlCollection.get_Item(Int32 index) +88
System.Web.UI.WebControls.TableCellCollection.get_Item(Int32 index) +56
_Default.SetPreviousData(Int32 rowsCount, Int32 colsCount) in C:\Users\ELindquist\Documents\Visual Studio 2010\WebSites\WebSite7\Default.aspx.vb:50
_Default.GenerateTable(Int32 rowsCount) in C:\Users\ELindquist\Documents\Visual Studio 2010\WebSites\WebSite7\Default.aspx.vb:83
_Default.Page_Load(Object sender, EventArgs e) in C:\Users\ELindquist\Documents\Visual Studio 2010\WebSites\WebSite7\Default.aspx.vb:10
System.Web.UI.Control.OnLoad(EventArgs e) +145
System.Web.UI.Control.LoadRecursive() +134
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3412



Left by Eric on Apr 27, 2011 12:19 AM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
Seems like your for loop condition exceeds an extra round that's why when accessing the controls by index it throws an error. Please try to debug your codes set a break point and step into it so that you will figure out whats going on there.

You may also try this:

Private Sub SetPreviousData(rowsCount As Integer, colsCount As Integer)
Dim table As Table = DirectCast(Me.Page.Master.FindControl("MainBody").FindControl("Table1"), Table)
If table IsNot Nothing Then
For i As Integer = 0 To rowsCount - 1
For j As Integer = 0 To colsCount - 1
Dim tb As TextBox = DirectCast(table.Rows(i).Cells(j).FindControl("TextBoxRow_" & i & "Col_" & j), TextBox)
tb.Text = Request.Form("ctl00$MainBody$TextBoxRow_" & i & "Col_" & j)
Next
Next
End If
End Sub
Left by Vinz on Apr 27, 2011 2:40 PM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
It still does not work. tb doesnot get set to any value. here is all of my code:

I therefore get a NullReference Exception on the request.form line.

Partial Class _Default
Inherits System.Web.UI.Page

Dim numOfRows As Integer = 1

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Generate the table on initial load
If Not IsPostBack Then
GenerateTable(numOfRows)
End If
End Sub

Protected Sub BTNAdd_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If (ViewState("RowsCount") IsNot Nothing) Then
numOfRows = CType(ViewState("RowsCount"), Integer)
GenerateTable(numOfRows)
End If
End Sub

Private Sub SetPreviousData(ByVal rowsCount As Integer, ByVal colsCount As Integer)
Dim table As Table = DirectCast(Me.Page.Master.FindControl("MainContent").FindControl("Table1"), Table)
If table IsNot Nothing Then
For i As Integer = 0 To rowsCount - 1
For j As Integer = 0 To colsCount - 1
Dim tb As TextBox = DirectCast(table.Rows(i).Cells(j).FindControl("TextBoxRow_" & i & "Col_" & j), TextBox)
tb.Text = Request.Form("ctl00$MainContent$TextBoxRow_" & i & "Col_" & j)
Next
Next
End If
End Sub

Sub GenerateTable(ByVal rowsCount As Integer)
Dim tbl As New Table()
tbl.ID = "Table1"

PlaceHolder1.Controls.Add(tbl)
Dim colsCount As Integer = 3
Dim rowCtr As Integer = 0
Dim colCtr As Integer = 0

For rowCtr = 0 To rowsCount
Dim tRow As New TableRow()
For colCtr = 1 To colsCount
Dim tcG As New TableCell()
Dim tbG As New TextBox()
tbG.ID = "TextRowBox_" & rowCtr & "Col_" & colCtr
tcG.Controls.Add(tbG)
tRow.Cells.Add(tcG)
Next
tbl.Rows.Add(tRow)
Next
Call SetPreviousData(rowsCount, colsCount)
ViewState("RowsCount") = rowsCount
End Sub
End Class
Left by Eric on Apr 28, 2011 10:11 AM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
Incidently if I don't call set previousdata it build the table correctly.
Left by Eric on Apr 28, 2011 10:17 AM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
Hi ,

i am able to add a new row and also keep the previous values assigned in the dynamic texts present in the dynamic asp table.

My Doubt ... Can i do come calculations using the values present in the textboxs and assign them back .

eg. textbox1.value = 50
textbox2.value = 20
now
i want textbox3.value = (textbox1.value/textbox2.value)
on button click
Left by Raj on Jun 02, 2011 3:58 PM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
@Raj,

Yes. Just iterate to each TextBox just like what I did in the SetPreviousData() method.
Left by Vinz on Jun 02, 2011 8:36 PM

# re: Master Page: Dynamically Adding Rows in ASP Table on Button Click event
Requesting Gravatar...
I'm having problems retaining values in my textbox whenever I refresh the page or add a new row. I am able to create new rows in the table that stay after refresh the page or add a new row, but not the values. I'm doing this on the default page. I call the AddRow function at both Page_Load and using an OnClick event on a button.

Code Snippet is:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

If Page.IsPostBack = False
AddRow_Function()
End If

End Sub

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

Sub AddRow_Function()

PlaceHolder.Controls.Clear()

' Create a Table and set its properties

Dim tbl As Table = New Table()
tbl.ID = "TextTable"

' Add the table to the placeholder control

PlaceHolder.Controls.Add(tbl)

For i As Integer = 0 To RowCount

Dim row As New TableRow()

Dim cell As New TableCell()

Dim element1 As New TextBox
element1.ID = "From_TextBox_" + System.Convert.ToString(i+1)
element1.Width = "150"
element1.Attributes.Add("runat", "Server")
element1.Attributes.Add("AutoPostBack", "True")
cell.Controls.Add(element1)

Dim element2 As New TextBox
element2.ID = "To_TextBox_" + System.Convert.ToString(i+1)
element2.Width = "150"
element2.Attributes.Add("runat", "Server")
element2.Attributes.Add("AutoPostBack", "True")
cell.Controls.Add(element2)

row.Cells.Add(cell)

tbl.Rows.Add(row)

Next

RowCount = tbl.Rows.count
SetPreviousData

End Sub
Private Sub SetPreviousData()

Dim tbl As Table = DirectCast(PlaceHolder.FindControl("TextTable"), Table)

If tbl IsNot Nothing

for i As Integer = 0 To RowCount - 1

'Extracting the Dynamic Controls from the Table

Dim From_tb As TextBox = DirectCast(tbl.Rows(i).Cells(0).FindControl("From_TextBox_" + System.Convert.ToString(i+1)),TextBox)
Dim To_tb As TextBox = DirectCast(tbl.Rows(i).Cells(0).FindControl("To_TextBox_" + System.Convert.ToString(i+1)), TextBox)

' Use Request objects for getting the previous data of the dynamic textbox

From_tb.Text = Request.Form("From_TextBox_" + System.Convert.ToString(i+1))
To_tb.Text = Request.Form("To_TextBox_" + System.Convert.ToString(i+1))

Next

End If

End Sub

Thanks in advance for any help you can provide...
Steve

P.S. I clipped this out of other code and changed/removed any non-related code to keep it short. Any content errors is due to the clipping.
Left by Steve Arndt on Nov 17, 2011 6:08 AM

comments powered by Disqus

Copyright © Vincent Maverick Durano | Powered by: GeeksWithBlogs.net