Trying to place a ListControl in page_init

Within my page I have a list.  In some cases this displays as a radiobuttonlist, and in other case as a checkboxlist.
This list is populated and read back by other subroutines.  From various tutorials it seems that dynamic controls must be generated in page_init if they are to be available across postbacks.

Given the following code, how do I add this listcontrol to the page in order for other subs to cast it as either of the 2 correct list types?

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)
      Dim lc As ListControl
      ph.Controls.Add(lc)
      lc.ID = "lc"
End Sub

Sub rePopulate(ByVal aNumber As Boolean) ' called later in the page
      Dim answers As ListControl = CType(ph.FindControl("lc"), ListControl)
      answers.Items.Clear()
      If aNumber Then
            answers = New RadioButtonList
      Else
            answers = New CheckBoxList
      End If
      ..... ' populate list items ....
End Sub

The page_init is giving an error:
   Value cannot be null.
   Parameter name: child
   ph.Controls.Add(lc)
LVL 25
RouchieAsked:
Who is Participating?
 
harshitsConnect With a Mentor Commented:
The problem which you are facing now is a universal problem of maintaining the state of dynamically created controls.

You'll need to implement some extra logic to maintain the state of the controls between postbacks.

Here is an example of how you can do the same...

http://www.codeproject.com/aspnet/retainingstate.asp

Harshit sheth
0
 
harshitsCommented:
Hi,

From code which you have given it is difficult to find out when Sub rePopulate is called and hence impossible to find the implications of the code inside the Sub.

However, I think the error which you are getting in the Page_Init function is because you have simply declared the ListControl object and not initialized it with the 'New' keyword and hence you are getting the error as " Value cannot be null."

Harshit Sheth
0
 
RouchieAuthor Commented:
Hi Harshit,
Yes you are correct, however, when I do this:
Dim lc As New ListControl

I get this error:
BC30569: 'New' cannot be used on a class that is declared 'MustInherit'.

The sub called rePopulate is fired in the page when a certain link is clicked.  Up until that point there should only be an empty listcontrol in the placeholder, so it shows nothing on screen.  The problem is that rePopulate is called many times during the total page execution, and each time may set the listControl to be either radio buttons or check boxes, therefore I cannot set it as a specific type in page_init - it must remain generic at that point.
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
harshitsCommented:
Hi Rouchie,

Just try putting this line

lc.ID = "lc"

before this one ph.Controls.Add(lc)

something like

Dim lc As ListControl
lc.ID = "lc"
ph.Controls.Add(lc)

I am not very confident on this, but I am gessing that probably the control needs to have a ID before it is added to placeholder and may be that is the reason you are getting the error.

Just try this.....hope it helps!

Harshit Sheth
0
 
RouchieAuthor Commented:
Thanks again Harshit, but another error is thrown:

   Object reference not set to an instance of an object.
   lc.ID = "lc"
0
 
harshitsCommented:
Rouchie,

I got think I got what you are trying to do now.

First of all you are creating the controls dynamycally, so there is no need to add the contorls in the placeholder in the Page_Init block. The code which you have written in the "Page_Init" block should be written in the "Sub rePopulate" immegiately after the controls are initialzed using the "New".

The reason being that the control is created dynamically in the "Sub rePopulate" and while you are trying to add it in the "Page_Init" block where the instance of the control is not yet created.

So here is what you can do

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)
     Dim lc As ListControl
End Sub

Sub rePopulate(ByVal aNumber As Boolean) ' called later in the page
     Dim answers As ListControl = CType(ph.FindControl("lc"), ListControl)
     answers.Items.Clear()
     If aNumber Then
          answers = New RadioButtonList
     Else
          answers = New CheckBoxList
     End If
 lc.ID = "lc"
     ph.Controls.Add(lc)
   

     ..... ' populate list items ....
End Sub
0
 
RouchieAuthor Commented:
When you call rePopulate for the first time, "lc" won't be in the placeholder though will it, because it hasn't been added there yet?
Your code (if I read it correctly!) seems to reference the control within the placeholder before it's actually added.
0
 
harshitsCommented:
Yeah, you are right; the correct code will be something like

Sub rePopulate(ByVal aNumber As Boolean) ' called later in the page
     Dim answers As ListControl
     If aNumber Then
          answers = New RadioButtonList
     Else
          answers = New CheckBoxList
     End If
   
     answers .ID = "answers "
     ph.Controls.Add(answers)
   

     ..... ' populate list items ....

End Sub

Also, you don’t need to define anything in Page_Init since the control is created and populated dynamically in the Sub rePopulate itself.

Harshit Sheth
0
 
harshitsCommented:
Hey,

really sorry missed something again

make this Dim answers As ListControl

as

Dim answers As New ListControl

Harshit Sheth
0
 
harshitsCommented:
goofed up! :-)

Just ignore the last comment.....that will actually give you an object reference error again

And that should be it!!!

Harshit Sheth
0
 
RouchieAuthor Commented:
>> Yeah, you are right; the correct code will be something like
By declaring the list control in this sub, when the page is posted back the control isn't actually there.  Here is the code that reads the values back:

Sub readChoices(...)
Dim a As ListControl
  If singleChoice Then
      a = CType(ph.FindControl("lc"), RadioButtonList)
  Else
      a = CType(ph.FindControl("lc"), CheckBoxList)
  End If
  For Each l As ListItem In a.Items  <-- "Object reference not set to an instance of an object."
      Trace.Warn(l.Selected)
      choiceArray.Add(l.Selected)
  Next
End Sub

>> Dim answers As New ListControl
BC30569: 'New' cannot be used on a class that is declared 'MustInherit'.
0
 
RouchieAuthor Commented:
Harshit,
Our last posts seemed to arrive together.  Not sure if you are still willing to help but if so I'd still be interested in getting my head around this :-)
0
 
harshitsCommented:
Hey Rouchie,

Always willing to help, that what I am here for!  Did not post any further comment as there was no further reply from you.

Anyways, As per my last comment, Just don’t use the 'New' keyword in the line which you got an error

>Dim answers As New ListControl
>BC30569: 'New' cannot be used on a class that is declared 'MustInherit'

And then let me know how the program behaves and if possible post the modified code here once again (that is of course if its still not working!)

Harshit Sheth

0
 
RouchieAuthor Commented:
Hi Harshit - thanks for getting back.
I've written the entire problem out in code here for you to see yourself.  This saves me chopping and pasting the relevant bits.
Within the code, the list populates fine, but when the page is posted back, the FindControl fails because the list isn't actually there (I think)!  Therefore I can't read the values back correctly.

<%@ Page Language="VB" Trace="true"  %>
<script runat="server">
      Sub createList(ByVal sender As Object, ByVal e As CommandEventArgs)
            If e.CommandArgument = "single" Then
                  loadChoices(True)
            Else
                  loadChoices(False)
            End If
            ViewState("loadChoices") = e.CommandArgument
            btn_submit.Visible = True
      End Sub
      
      Sub loadChoices(ByVal singleChoice As Boolean)
            Dim lc As ListControl
            If singleChoice Then
                  lc = New RadioButtonList()
            Else
                  lc = New CheckBoxList()
            End If
            lc.Items.Add(New ListItem("Value 0", 0))
            lc.Items.Add(New ListItem("Value 1", 1))
            lc.Items.Add(New ListItem("Value 2", 2))
            ph.Controls.Add(lc)
            lc.ID = "lst_choices"
      End Sub
      
      Sub readChoices(ByVal sender As Object, ByVal e As CommandEventArgs)
            Dim lc As ListControl
            Dim singleAnswer As String = ViewState("loadChoices")
            If singleAnswer = "single" Then
                  lc = CType(ph.FindControl("lst_choices"), RadioButtonList)
            Else
                  lc = CType(ph.FindControl("lst_choices"), CheckBoxList)
            End If
            For Each l As ListItem In lc.Items
                  Trace.Warn(l.Text & ": " & l.Selected)
            Next
      End Sub
</script>
<!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>My Page</title>
</head>
<body>
    <form runat="server">
            <asp:Button ID="btn1" runat="server" Text="Create Single Choice List" OnCommand="createList" CommandArgument="single" />
            <asp:Button ID="btn2" runat="server" Text="Create Multi Choice List" OnCommand="createList" CommandArgument="multi" />
            <asp:PlaceHolder ID="ph" runat="server" />
            <asp:Button id="btn_submit" runat="server" Text="Submit" OnCommand="readChoices" Visible="false" />
    </form>
</body>
</html>
0
 
RouchieAuthor Commented:
Right, let me crank up VWD and do a test page and I'll get back to you! :-)
0
 
RouchieAuthor Commented:
The link provided a nice way around what I'm trying to accomplish.  Thanks Harshit! :-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.