ASP.NET: How to change the itemTemplate used per row in an

asp.net

Existing code is using an asp:repeater to build an HTML table. (emphasis on the existing design). This is some partial pseudo-code to generate the table:

<asp:repeater OnItemDataBound="ItemDataBound" ... >

   <headertemplate>
      <table>
         <thead>
            <tr>
               <td>Date</td>
               <td>Type</td>
               <td>Action</td>
            </tr>
         </thread>
   </headertemplate>

   <itemtemplate>
      <tr>
         <td><%# GetTextForThis((MyItem)Container.DataItem) %></td>
         <td><%# GetTextForThat((MyItem)Container.DataItem) %></td>
         <td><%# GetTextForTheOther((MyItem)Container.DataItem) %></td>
      </tr>
   </itemtemplate>

   <footertemplate>
         </tbody>
      </table>
   </footertemplate>

</asp:repeater>

But now it is needed that (some) items display differently, and it is needed that it is done using a COLSPAN=3, and the entire item will be one cell:

   <itemtemplate>
      <tr>
         <td colspan="3">
            <img src="<%# GetImageSrcForFoo((MyItem)Container.DataItem) %>
            <a href="<%# GetHrefForFoo((MyItem)Container.DataItem) %>
         </td>
      </tr>
   </itemtemplate>

Given:

  • the page uses a repeater to build an HTML table
  • the design requires some table rows to span columns

How can i do this?

i was hoping for something like:

   <itemtemplate id="thisThatTheOtherItemTemplate">
      <tr>
         <td><%# GetTextForThis((MyItem)Container.DataItem) %></td>
         <td><%# GetTextForThat((MyItem)Container.DataItem) %></td>
         <td><%# GetTextForTheOther((MyItem)Container.DataItem) %></td>
      </tr>
   </itemtemplate>


   <itemtemplate id="fooItemTemplate">
      <tr>
         <td colspan="3">
            <img src="<%# GetImageSrcForFoo((MyItem)Container.DataItem) %>
            <a href="<%# GetHrefForFoo((MyItem)Container.DataItem) %>
         </td>
      </tr>
   </itemtemplate>

and somehow magically be able to have the OnDataBind event tell the repeater which template to use. Is this possble?

Answer

Although both answers are right and good, i'd rather use the first suggestion; which involves having display code in the aspx file, rather than building HTML manually in a code-behind. (i don't want to ever have to build HTML in code again)

   <itemtemplate>
      <asp:PlaceHolder ID="thing1" runat="server">
         <tr>
            <td><%# GetTextForThis((MyItem)Container.DataItem) %></td>
            <td><%# GetTextForThat((MyItem)Container.DataItem) %></td>
            <td><%# GetTextForTheOther((MyItem)Container.DataItem) %></td>
         </tr>
      </asp:PlaceHolder>

      <asp:PlaceHolder ID="thing2" visible="false" runat="server">
         <tr>
            <td colspan="3">
               <img src="<%# GetImageSrcForFoo((MyItem)Container.DataItem) %>
               <a href="<%# GetHrefForFoo((MyItem)Container.DataItem) %>
            </td>
         </tr>
   </itemtemplate>

and in the code-behind:

protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
   // if the data bound item is an item or alternating item (not the header etc)
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
   {
      // get the associated object
      Object item = .Item.DataItem;
      if (item == null)
         return;

      Control thing1 = e.Item.FindControl("thing1");
      Control thing2 = e.Item.FindControl("thing2");

      if (item is MyClassThatICreated)
      {
         thing1.Visible = false;
         thing2.Visible = true;
      }
      else
      {
         thing1.Visible = true;
         thing2.Visible = false;
      }
      ...
}

Best Solution

Place two ASP:Placeholder controls in your item template. In the codebehind, on the ItemDataBound event, determine which style you want to show, and hide one placeholder.