Repeater Control And CheckboxList

I have a Repeater control with a CheckBoxList item in it.

  1. How can I give a dinamic ID to the CheckBoxList for each row?
  2. If I can’t assign a dynamic ID, how can I reference to each CheckBoxList as I need to update the database on selection changes.

Any help would be greatly appretiated!

I tried:

<asp:Repeater ID="rptrEmailSubscriptions" OnItemCreated="BindSubscriptions" Runat="server">
	<ItemTemplate>
		<b><%# Container.DataItem("Email")%></b>
		<asp:checkboxlist [COLOR=Red]id='cblSubscriptions_<%# Container.DataItem("EmailID")%>'[/COLOR] runat="server" />
	</ItemTemplate>
	<SeparatorTemplate>
		<hr>
	</SeparatorTemplate>
</asp:Repeater>

But it give me an error - “Parser Error Message: ‘cblSubscriptions_<%# Container.DataItem(“EmailID”)%>’ is not a valid identifier.” on the red text above.

Then to bind the CheckboxList items and select the subscriptions by calling the control via the dynamic assigned ID:

    Private Sub BindSubscriptions(ByVal sender As Object, ByVal e As DataGridItemEventArgs)

        If e.Item.ItemType = ListItemType.Item Or _
           e.Item.ItemType = ListItemType.AlternatingItem Then
            Dim cblSubscriptions As CheckBoxList = e.Item.FindControl("cblSubscriptions_" & e.Item.DataItem("EmailID"))

            objConn.Close()
            objConn.Open()

            objCmd = New SqlCommand("SELECT * FROM tlkpDistribution ORDER BY Name", objConn)
            objRdr = objCmd.ExecuteReader()
            cblSubscriptions.DataSource = objRdr
            cblSubscriptions.DataValueField = "DistributionID"
            cblSubscriptions.DataTextField = "Name"
            cblSubscriptions.DataBind()
            objRdr.Close()

            'Get subscriptions and select CheckBoxList item selections
            objCmd = New SqlCommand("SELECT * FROM tblSubscription WHERE (UserID=" & strUserID & ") AND (EmailID=" & e.Item.DataItem("EmailID") & ")", objConn)
            objRdr = objCmd.ExecuteReader()
            While objRdr.Read()

                If Not cblSubscriptions.Items.FindByValue(objRdr.Item("DistributionID").ToString) Is Nothing Then
                    cblSubscriptions.Items.FindByValue(objRdr.Item("DistributionID").ToString).Selected = True
                End If

            End While

            objRdr.Close()
            objConn.Close()

        End If

    End Sub

Can use:

rptrEmailSubscriptions.Items[i].FindControl(“cblSubscriptions”)

to access each CheckBoxList in everyone of your RepeaterItems. I think for VB.NET you just change [i] to (i). Just put that in a for loop in your button submit event method and you will have access to all the CheckBoxLists.

Also, you are going to have to upgrade that repeater to a DataList. Think of a repeater like a DataReader. They are both fast, forward only, output only. Going back and forth is a bit tricky without other persistence options.

I think you are making it more complicated than it really is.

A repeater is a namingcontainer meaning that each item will act as a seperate namespace. Therefore, there’s no need to assign page-wide unique IDs to items in the template. Just assign any ID that unique within the template. This will do:

<asp:checkboxlist id='cblSubscriptions' runat="server" />

even if you assign a page-wide unique ID it will still be “nested” inside the repeater (another effect of the repeater being a namingcontainer).

Now to find the checkboxlist during the ItemCreated event just do

Dim cblSubscriptions As CheckBoxList = e.Item.FindControl("cblSubscriptions" )

The error message that you are getting is b/c you are using a databinding expression to generate an identifier. Databinding occurs too late in the page lifecycle to be used to generate identifiers dynamically. And as outlines above there’s really no need.

As a sidenote, this is also why controls have both an ID and a ClientID property: The ID property is the declared (local if you will) identifier, while ClientID id the “global” ID that has been prefixed with the naming container’s identifier. This is the ID that can be used from javascript.

On second thought I think you should pay attention to the DataList as wwb_99 advised you. Any reason why you are not using a datalist?

There’s nothing wrong with using the Repeater, I try and use a Repeater as much as I can. What Benjymouse said would sort you out no problem.

:slight_smile:

What Benjymouse said would sort you out no problem.

I didn’t claim that using datalist would sort out his problem. My first post answered his original problem, and even explained why he was having the problem.

Thats the post I was talking about :slight_smile:

If you think that it’ll sort out no problem, then I sincerely believe that you should address the original problem constructively. :shifty:

Ok, I have changed the code so that it is a DataList.

I now have the following error which I dont inderstand:

This code binds the DataList

    Private Sub BindEmailDataList()

        objConn.Open()
        objCmd = New SqlCommand("SELECT * FROM tblUserEmail WHERE UserID=" & strUserID & " ORDER BY Email", objConn)
        objRdr = objCmd.ExecuteReader()
        dlEmailSubscriptions.DataSource = objRdr
        dlEmailSubscriptions.DataBind()
        objRdr.Close()
        objConn.Close()

    End Sub

Then on creation the following is done on each row to bind the datalist.

    Public Sub dlEmailSubscriptions_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs)

        If e.Item.ItemType = ListItemType.Item Or _
           e.Item.ItemType = ListItemType.AlternatingItem Then
            Dim cblSubscriptions As CheckBoxList = e.Item.FindControl("cblSubscriptions")
            Dim objEmailRdr As SqlDataReader
            Dim objEmailCmd As SqlCommand

            objEmailCmd = New SqlCommand("SELECT * FROM tlkpDistribution ORDER BY Name", objConn)
            [COLOR=Red]objEmailRdr = objEmailCmd.ExecuteReader()[/COLOR]
            cblSubscriptions.DataSource = objEmailRdr
            cblSubscriptions.DataValueField = "DistributionID"
            cblSubscriptions.DataTextField = "Name"
            cblSubscriptions.DataBind()
            objEmailRdr.Close()

        End If

    End Sub

This returns the following error for the line highlighted above:
There is already an open DataReader associated with this Connection which must be closed first.

I don’t understand this error as the reader for the DataList is declared as objRdr while this one is objEmailRdr.

I also tried closing the objRdr, but then I get:
Invalid attempt to FieldCount when reader is closed

Readers use up open connections. Use DataSet for objRdr to bind the list, then you can use DataReader in dlEmailSubscriptions_ItemCreated.

I have changed my code to make use of a DataView and DataAdaptor.

My next question is, how do I set the values as SELECTED for items? I have tried the code below and it execute without errors, but nothing is selected.

My code:

    Public Sub dlEmailSubscriptions_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs)

        If e.Item.ItemType = ListItemType.Item Or _
           e.Item.ItemType = ListItemType.AlternatingItem Then
            Dim cblSubscriptions As CheckBoxList = e.Item.FindControl("cblSubscriptions")

            Dim objEmailDA As SqlDataAdapter
            Dim objEmailDS As New DataSet
            Dim objEmailDV As DataView

            objEmailDA = New SqlDataAdapter("SELECT * FROM tlkpDistribution ORDER BY Name", objConn)
            objEmailDA.Fill(objEmailDS, "DistributionLists")
            objEmailDV = objEmailDS.Tables("DistributionLists").DefaultView
            cblSubscriptions.DataSource = objEmailDV
            cblSubscriptions.DataValueField = "DistributionID"
            cblSubscriptions.DataTextField = "Name"
            cblSubscriptions.DataBind()


            'Get subscriptions and select CheckBoxList item selections
            Dim EmailID As String
            Dim DistributionID As String
            objConn.Open()
            objCmd = New SqlCommand("SELECT tblSubscription.EmailID, tblSubscription.DistributionID, tlkpDistribution.Name AS DistriburtionList, tblUser.UserID, tblUser.Username, tblUserEmail.Email, tblUser.Name, tblUser.Surname FROM tlkpDistribution RIGHT OUTER JOIN tblSubscription ON tlkpDistribution.DistributionID = tblSubscription.DistributionID LEFT OUTER JOIN tblUser LEFT OUTER JOIN tblUserEmail ON tblUser.UserID = tblUserEmail.UserID ON tblSubscription.EmailID = tblUserEmail.EmailID WHERE (tblSubscription.EmailID=" & e.Item.DataItem("EmailID") & ")", objConn)
            objRdr = objCmd.ExecuteReader()
            While objRdr.Read()

                EmailID = objRdr.Item("EmailID").ToString
                DistributionID = objRdr.Item("DistributionID").ToString

                If Not cblSubscriptions.Items.FindByValue(objRdr.Item("DistributionID").ToString) Is Nothing Then
                    cblSubscriptions.Items.FindByValue(objRdr.Item("DistributionID").ToString).Selected = True
                End If

            End While
            objConn.Close()

        End If

    End Sub

See http://www.sitepoint.com/forums/showthread.php?p=2015775#post2015775 for resolution