Using FindControl to find a repeater nested inside a repeater with HeaderTemplate or FooterTemplate defined


I just today cracked a problem which consumed my Friday afternoon and a big chunk of this morning.  This was something i hadn’t come across in .net when using repeaters before. 

On the aspx side I had a repeater embedded within a repeater;

  <asp:Repeater ID="rptAddedSeries" runat="server">
    <headerTemplate>
      <div id="seriesHeader">
    </headerTemplate>
    <itemTemplate>
      <h2>
        <%#Container.DataItem().Title%>
      </h2>
      <asp:Repeater ID="rptBooks" runat="server">
        <headerTemplate><ul></headerTemplate>
        <itemTemplate>
          <li>
            <%#Container.DataItem().BookID%>
          </li>
        </itemTemplate>
        <footerTemplate>
          </ul>
        </footerTemplate>
      </asp:Repeater>
    </itemTemplate>
    <footerTemplate>
      </div>
    </footerTemplate>
  </asp:Repeater>

I simply wanted to populate the inner repeater and perform the databinding.  The code i had worked fine- using FindControl to grab the inner repeater then setting the datasource and executeing DataBind().  However, when i added the HeaderTemplate and FooterTemplate to the parent “rptAddedSeries” control, the FindControl suddenly stopp working and i started getting a NullReferenceException when trying to set my DataSource.

Protected Sub rptAddedSeries_ItemDataBound(ByVal sender As Object,  ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs)Handles rptAddedSeries.ItemDataBound
   Dim this_repeater_item As RepeaterItem = DirectCast(sender, Repeater).Controls.Item(_repeater_counter)
   Dim child_repeater As Repeater = DirectCast(this_repeater_item.FindControl("rptBooks"), Repeater)
   child_repeater.DataSource = _highlight.Highlights_Seriess(_repeater_counter).Highlight_Series_Books 
   child_repeater.DataBind() 
   _repeater_counter += 1
End Sub

After a bit of googling I found a forum post on asp.net forums by someone with a similar issue.  The ItemDataBound event occurs against each part of the your repeater item- meaning if you have a HeaderTemplate and FooterTemplate as well as your standard ItemTemplate, the ItemDataBound will execute 3 times.  So I added a condition at the start of the function to ensure that i was running my code only during the ItemTemplate data binding;

If e.Item.ItemType = ListItemType.Item Then
  ...  
End If

However i was still having issue’s with the FindControl failing.  Reading down the same forum post i found a note mentioning that FindControl wouldn’t work directly against the RepeaterItem but there was nothing to say whatI should be running it against.  Considering the it was the e (RepeaterItemEventArgs) object we tested to find the current ItemType, it stood to reason that the actual item might be contained within there so i modified the method and it worked perfectly;

Protected Sub rptAddedSeries_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptAddedSeries.ItemDataBound
  If e.Item.ItemType = ListItemType.Item Then
    'Dim this_repeater_item As RepeaterItem = DirectCast(sender, Repeater).Controls.Item(_repeater_counter)
    'Dim child_repeater As Repeater = DirectCast(this_repeater_item.FindControl("rptBooks"), Repeater) 
    'Dim child_repeater As Repeater = DirectCast(this_repeater_item.TemplateControl.FindControl("rptBooks"), Repeater)

    Dim child_repeater As Repeater = DirectCast(e.Item.FindControl("rptBooks"), Repeater) 
    child_repeater.DataSource = _highlight.Highlights_Seriess(_repeater_counter).Highlight_Series_Books 
    child_repeater.DataBind() 
    _repeater_counter += 1 
  End If 
End Sub

Hope this save’s someone else a few hours of tearing their hair out!

  1. No comments yet.
(will not be published)