Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET: How to change the itemTemplate used per row in an <asp:repeater>?

Tags:

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;
      }
      ...
}
like image 532
Ian Boyd Avatar asked Jan 24 '23 23:01

Ian Boyd


2 Answers

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.

like image 57
FlySwat Avatar answered Feb 22 '23 22:02

FlySwat


An alternative to Jonathan's suggestion is to just dynamically build the item on the backend in the ItemDataBound event, some people find that easier to work with, rather than toggling visibility.

I personally in this case would just put a literal in, with mode="Passthrough" and would build it on the backend.

like image 23
Mitchel Sellers Avatar answered Feb 22 '23 22:02

Mitchel Sellers