Dynamic Controls: Trying to understand the logical flow?

I've been reading countless articles describing how to create dynamic server controls, then assign values to them.  I'm having difficulty assigning values as I keep getting an "Object reference not set to an instance of an object" error.  I am unable to paste my exact code, but here is basically what I'm trying to accomplish: I have a house with 1 to many windows and the user can add windows as they see fit.  I'm dynamically creating a table to hold the windows, and ultimately want to recreate/populate the table when the user needs to update the number of windows.

House.aspx:
Contains a server table, id="houseTable"

House.aspx.vb:
***Page_Init()***
If session("mode") = "new" then
newTable() 'Not too concerned with new tables
Else If session("mode") = "edit" then
   existingTable()
End if
End if

Sub existingTable()
'numWin = retrieve # of window rows
for x=1 to numWin
   rowCtr = rowCtr + 1
   Dim tRow As New TableRow
   Dim tCell As New TableCell
   Dim _textbox As New TextBox
     _textBox.id = "Window" & rowCtr
    tCell.Controls.Add(_textbox)
   tRow.Cells.Add(tCell)
Next
houseTable.Rows.Add(tRow)
End Sub

***Page_Load***
If not Page.IsPostBack then
  If session("mode") = "edit" then
       'Connect to the database and get data
   for x=1 to numWin
      rowCtr = rowCtr + 1
      "Window" & rowCtr = RS.Window  'I know this isn't correct syntax, but I'm just trying to assign the values as I iterate thru each control and its named ID.  I attempted to use:
           for each C As Control in Controls
                 if ((C.GetType.ToString.Equal("System.Web.UI.WebControls.TextBox") And (C.ID = "Window" & rowCtr)) then
                     'assign a value
               end if ' but the above didn't work either.

next

End If
End If
      
Any help you can provide is greatly appreciated!

0
SABmore
11/10/2005 7:26:30 PM
asp.net.web-forms 93655 articles. 6 followers. Follow

5 Replies
439 Views

Similar Articles

[PageSpeed] 31

Hi,


sorry if I don't address your question about dynamic controls, but I want to propose you an alternative approach to the problem, using a Repeater.


This task is very common: create a certain number of server controls based on the value of a parameter. Let's say the parameter is numeric and contains, implicitly or explicitly, the number of controls to be created.


In your case, this parameter is the number of "windows" to create, each one represented by a table row containing a TextBox control.


First, we can declare a Repeater control that creates the TextBoxes needed,


<table cellspacing="0" cellpadding="0" border="1">


  <asp:Repeater id="repWindows" runat="server">


    <ItemTemplate>
      <tr>
        <td>
          <asp:TextBox id="txtWindow" runat="server"></asp:TextBox>
        </td>
      </tr>
    </ItemTemplate>


  </asp:Repeater>


</table>


Now, in the server code (codebehind), knowing the number of rows to create, we can bind the repeater. For example,


 int nRows = // number of rows to create.

 // Create a DataSource for the Repeater. This can be used to add useful infos
 // such as database IDs or other stuff. In this example, fill it with an index.
 int[] dsource = new int[nRows];


 for(int k = 0; k < nRows; k++)
   dsource[k] = k;


 repWindows.DataSource = dsource;
 repWindows.DataBind();


The Repeater does what you tried to do with the server Table and dynamic TextBoxes: it adds a dynamic number of rows containing a TextBox to a HTML table.


Now, it is interesting to implement two actions,


1) Fill the value of each TextBox (the 'edit' mode).
2) Retrieve the value of each TextBox.


To fill the TextBoxes, we can declare an event handler for the Repeater's ItemDataBound event, get a reference to the TextBox and fill it.


To retrieve the value of each TextBox, we can loop through the Repeater's Items, get a reference to the TextBox and retrieve its value.


Maybe this approach requires a little more coding than using dynamic controls, but I think it is more robust, easy to maintain/debug and offers a general solution to this kind of task.


If you find this approach useful for your task and have problem in the implementation, I can post a simple example written in C# or give further explanations.


Alessandro Gallo | Blog | My book: ASP.NET AJAX In Action
0
Garbin
11/11/2005 9:59:25 AM
Garbin, once again thanks for the info.  I have looked into using server controls such as the repeater, but I have a question.  I am using NHibernate for my data access, so rather than requiring me to specify a datasource, it handles that for me, and in the instance above with # of windows I return an array list (IList).  In order to use the server controls, all of the examples I've seen require you to specify the datasource, then you can call the objects in your SQL directly...is this totally necessary or is there a way around this?  In other words, would it be possible to "bind" my returned IList to the server control?  Thanks again.
0
SABmore
11/11/2005 3:20:40 PM

Hi,


yes, you can bind the Repeater control to an IList, just assign it to the DataSource property of the Repeater:


repWindows.DataSource = myIList;
repWindows.DataBind();


This will generate a number of Repeater items equal to the number of objects contained in your IList, and each object will be accessible by referencing the DataItem property of each item created (an item is a RepeaterItem instance).


Alessandro Gallo | Blog | My book: ASP.NET AJAX In Action
0
Garbin
11/11/2005 4:19:09 PM
Garbin:

I've done as you suggested with the repeater and am seeing good results.  One other question, how would I add additional rows to the repeater?  In other words, say I have retrieved data and displayed it in 2 rows, now I'd like to add 3 more rows (for a total of 5) to the repeater in which I could enter/edit data.  Thanks!
0
SABmore
11/15/2005 10:30:59 PM

Hi,


basically you have to re-build your data source (the IList) and re-bind the repeater with the statements


   repWindows.DataSource = myNewIList;
   repWindows.DataBind();


The new IList will contain the 5 row-data to display (3 row-data from previous binding + 2 new row-data).


However, keep in mind that re-binding the repeater deletes the changes that you have made to your data (for example, if I edit the text in a TextBox and then do a postback and rebind the repeater, my changes are deleted).


One solution would be looping through the repeater items before re-binding, and save the changes made to the rows. Then, retrieve these rows and the new rows from the database and re-bind the repeater.


Another approach is caching the IList that have been returned the first time, retrieve it from the cache (or from the mapper, if it has been deleted from the cache), save the changes made to the rows, merge the new rows to that IList and re-bind the repeater.


I don't know which approach to suggest, because I'm not sure of your Page behavior. If you give a more accurate description of the Page flow, we can work on the concrete case.


Alessandro Gallo | Blog | My book: ASP.NET AJAX In Action
0
Garbin
11/16/2005 10:20:26 AM
Reply: