0

I have searched all around for a solution, and have stepped through my code, but I can't seem to find my childRepeater in a button click event. The button is placed in the footer of familyRepeater, if that matters for this issue.

The childRepeater is created dynamically in code behind.

Here is my click event:

  Protected Sub EnrollAllButton_Click(sender As Object, e As EventArgs)

    familyRepeater.DataSource = Session("Families")
    familyRepeater.DataBind()
    
    For Each item As RepeaterItem In familyRepeater.Items
      If (item.ItemType = ListItemType.Item OrElse item.ItemType = ListItemType.AlternatingItem) Then

        ' this never finds childRepeater. It is null for every item
        Dim childRepeater As Repeater = TryCast(item.FindControl("childRepeater"), Repeater)

        If childRepeater IsNot Nothing Then

          For Each child As RepeaterItem In childRepeater.Items
            Dim radio1 As RadioButtonList = CType(child.FindControl("AttendanceRBL"), RadioButtonList)
            radio1.Items.FindByText("Enrolled").Selected = True

          Next
        End If
      End If
    Next
  End Sub

What am I missing to get to the child repeater and its controls? When I inspect the page in the browser, I can drill down to the child repeater and see all the child controls there.

Here is my aspx page:

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Repeater.aspx.vb" Inherits="RepeaterSample.Repeater" enableEventValidation="false" %>

<%@ Import Namespace="System.Data" %>

<html>

<head runat="server">
    <title></title>
    <link href="~/StyleSheet1.css" rel="stylesheet" type="text/css" />
</head>
  
<body>
  <form runat="server">

    <div id="NestedRepeaters">
      <p>Repeater: </p>
      <p>Family: <asp:Label ID="familyMsg" runat="server" Text="ViewMode"></asp:Label></p>
       <p>Child: <asp:Label ID="childMsg" runat="server" Text=""></asp:Label></p>

      <!-- begin parent repeater -->
      <asp:Repeater ID="familyRepeater" runat="server" OnItemCommand="familyRepeater_ItemCommand" >
        <HeaderTemplate>
          <table >
            <tr>
              <th colspan="4"><asp:Label runat="server" Text="Last Name, First Name, M.I." Font-Bold="true" Width="300"></asp:Label></th>
              <th><asp:Label runat="server" Text="FICN" Font-Bold="true" Width="100"></asp:Label></th>
              <th><asp:Label runat="server" Text="Program Code" Font-Bold="true" Width="100"></asp:Label></th>
              <th colspan="2"><asp:Label runat="server" Text="Attendance Status" Font-Bold="true" Width="200"></asp:Label></th>
              <th><asp:Label runat="server" Text="Update" Font-Bold="true" Width="80"></asp:Label></th>
            </tr>
        </HeaderTemplate>
        <ItemTemplate>
          <tr class="spaceAbove">
            <td><b>Family:</b></td>
            <td colspan="3"><%# DataBinder.Eval(Container.DataItem, "FamilyName") %></td>
            <td><%# DataBinder.Eval(Container.DataItem, "FICN") %> </td>
            <td></td>
            <td></td>
            <td></td>          
            <td style="text-align: center;"> 
    
           <asp:LinkButton ID="editFamily" runat="server" Text="Edit Family" OnClick="OnEdit" CommandName="EditFamily" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FamilyID") %>' ></asp:LinkButton>
                <asp:LinkButton ID="updateFamily" Text="Update" runat="server" Visible="false" OnClick="OnUpdate" CommandName="UpdateFamily"/>
                <asp:LinkButton ID="cancelFamily" Text="Cancel" runat="server" Visible="false" OnClick="OnCancel" CommandName="CancelFamily" />
             
            </td>
          </tr>
          <!-- begin child repeater -->
          <asp:Repeater ID="childRepeater" runat="server" OnItemDataBound="ChildRepeater_ItemDataBound" DataSource='<%# (CType(Container.DataItem, DataRowView)).Row.GetChildRows("FamilyChildRelation") %>' OnItemCommand="ChildRepeater_ItemCommand" >
            <ItemTemplate>
              <tr>
                <td></td>
                <td colspan="4" style="vertical-align: top;">Child: <asp:Label runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "ChildName") %>' />
                </td>
                <td style="text-align: center;">
                  <asp:PlaceHolder ID="programPlaceHolder" runat="server" ></asp:PlaceHolder>
                </td>
                <td style="text-align: center;">
                  <asp:PlaceHolder ID="attendancePlaceHolder" runat="server" ></asp:PlaceHolder>
                </td>
                <td></td>
                <td ></td>
              </tr>       
            </ItemTemplate>
          </asp:Repeater>
          <!-- end child repeater -->
        </ItemTemplate>
        <FooterTemplate> 
          <td colspan ="4" style="text-align: center; ">
          <asp:button ID="EnrollAllButton" runat="server" text="Enroll All" OnClick="EnrollAllButton_Click" />
          <asp:button ID="AttendAllButton" runat="server" text="Attend All" OnClick="AttendAllButton_Click" />

          </td> 
          </table>
        </FooterTemplate>
      </asp:Repeater>
      <!-- end parent repeater -->
    </div>
  </form>
</body>
</html>

Here is my pageload and binding code:

  Public Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
 
    bindData()
    If Not IsPostBack Then ' Do this for first time page loads
      familyRepeater.DataSource = Session("Families")
      familyRepeater.DataBind()
    End If
  End Sub

  Private Sub bindData()
    'test data
    Dim RptYrMo As String = "202007"
    Dim agency As Integer = 879
    Dim subAgencyCode As String = "000"

    Dim familiesDataSet As DataSet = New DataSet()

    ' Fill data tables for families, children, and settings
    dtFamilies = Attendance.GetFamilies(RptYrMo, agency, subAgencyCode)
    dtChildren = Attendance.GetChildren(RptYrMo, agency, subAgencyCode)

    'Add data tables to data set
    familiesDataSet.Tables.Add(dtFamilies)
    familiesDataSet.Tables.Add(dtChildren)
    'Add relationship
    familiesDataSet.Relations.Add("FamilyChildRelation", familiesDataSet.Tables("Families").Columns("FamilyID"), familiesDataSet.Tables("Children").Columns("FamilyID"))

    'Bind the data set
    familyRepeater.DataSource = familiesDataSet.Tables("Families")
    familyRepeater.DataBind()

    Session("Families") = familiesDataSet.Tables("Families")

  End Sub

Thank you for your time.

Tonya
  • 35
  • 7
  • You call `familyRepeater.DataBind()` and then start looking for the Child Repeater. If you create it dynamically you need to recreate it on every Page Load (and that includes a PostBack) or after calling DataBind on the parent. – VDWWD Dec 07 '20 at 19:53
  • @VDWWD I did call ```familyRepeater.DataBind()``` at the beginning of this event. – Tonya Dec 07 '20 at 19:55
  • I added more of my code to my original post – Tonya Dec 07 '20 at 20:12
  • Page_Load is too late in the lifecycle to bind the data. Any events on the inner repeater won't fire, because it won't exist yet in the part of the page lifecycle that wire events together. – Joel Coehoorn Dec 09 '20 at 00:16

2 Answers2

1

I found the answer. I had to change this line:

Dim childRepeater As Repeater = TryCast(item.FindControl("childRepeater"), Repeater)

to this:

Dim childRepeater As WebControls.Repeater = TryCast(item.FindControl("childRepeater"), WebControls.Repeater)

Tonya
  • 35
  • 7
0

I would change the whole approach here. Rather than trying to update the controls, I would update the data source, and then call bindData() again so the controls are built from that new data as they are supposed to be.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794