17

I would like to be able to use the ASP.Net Repeater control to create an HTML Table that has three columns and as many rows as necc.

For example if the Data were to look like this

"Phil Hughes"

"Andy Petite"

"CC Sabathia"

"AJ Burnett"

"Javier Vazquez"

I would like the resulting table to be like

<table>
 <tr>
  <td>Phil Hughes</td>
  <td>Andy Petite</td>
  <td>CC Sabathia</td>
 </tr>
 <tr>
  <td>AJ Burnett</td>
  <td>Javier Vazquez</td>
  <td></td>
 </tr>
</table>

How can I do this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
etoisarobot
  • 7,684
  • 15
  • 54
  • 83

6 Answers6

20

Repeater is not the ideal control to do that. If you're using .NET 3.5 you should use ListView instead. Here's an example that does what you're asking for.

<asp:ListView ID="myListView" runat="server" 
   DataSourceID="YOURDATASOURCE" GroupItemCount="3">

   <LayoutTemplate>
      <table>
         <tr>
            <td>
               <table border="0" cellpadding="5">
                  <asp:PlaceHolder runat="server" ID="groupPlaceHolder"></asp:PlaceHolder>
               </table>
            </td>
         </tr>
      </table>
   </LayoutTemplate>

   <GroupTemplate>
      <tr>
         <asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
      </tr>
   </GroupTemplate>

   <ItemTemplate>
      <td>
         <%# Eval("FullName") %>
      </td>
   </ItemTemplate>
</asp:ListView>
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Merrimack
  • 1,736
  • 14
  • 12
16

It's better to use a DataList control intstead as it has the interesting properties RepeatColumns and RepeatDirection.

Kris van der Mast
  • 16,343
  • 8
  • 39
  • 61
  • 2
    I was thinking the same thing but I assumed that a `Repeater` was required or extending existing code. If not this is a good read "When to us a DataGrid, DataList or Repeater" http://msdn.microsoft.com/en-us/library/aa479015.aspx. A little old (we now have `ListView` and `GridView`) but the concepts still apply. – Kelsey Aug 09 '10 at 19:05
  • 1
    DataList has crappy styling! – ATL_DEV Apr 09 '14 at 19:14
  • @user148298 it generates the html you want it to emit so I'm not really understand your comment. As always: Crap in, Crap out :-). – Kris van der Mast Apr 11 '14 at 12:42
  • @XIII The generated HTML is horrible and very difficult to style. ListView or Repeater is better IMHO. At least you have some control over the HTML. – ATL_DEV Apr 12 '14 at 15:53
  • What if it is multiple DIVs instead of a table: http://stackoverflow.com/questions/31254126/how-to-generate-dynamic-labels-and-use-the-column-name-and-value-as-the-text – SearchForKnowledge Jul 06 '15 at 19:52
  • you will face issue when sorting with DataList Control – mzonerz Aug 07 '19 at 07:13
11

Much simpler than all the examples listed here; You don't need to use a list view or do anything in the code behind.

  <asp:Repeater ID="ExampleRepeater" runat="server" >
    <HeaderTemplate>
        <table>
            <tr>
                <th>   Column 1
                </th>
                <th>   Column 2
                </th>
                <th>   Column 3
                </th>
            </tr>
    </HeaderTemplate>
    <ItemTemplate>
        <tr>
            <td>
                <asp:LinkButton ID="RemoveButton" runat="server" Text='Remove' CommandName="Remove"
                    CommandArgument='<%# Eval("ID") %>' CausesValidation="false"></asp:LinkButton>
            </td>
            <td>

                <asp:LinkButton ID="EditLink" runat="server" Text='<%# Eval("Name")  %>'
                    CommandName="Edit" CommandArgument='<%# Eval("ID") %>' CausesValidation="false"></asp:LinkButton>

            </td>
            <td>
                <asp:Label ID="CommentTextBox" runat="server" Text='<%# Eval("Comment")  %>' />
            </td>
        </tr>
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>
Alex Z
  • 1,362
  • 15
  • 16
  • 2
    I didn't know if we could create table using Repeaters like this. Learned something new. Thanks – Abhishek Shrivastava Sep 12 '12 at 21:33
  • how does this answer the question? – drzaus Jan 30 '13 at 14:08
  • 1
    @drzaus This perfectly answers the question (by using the repeater control), even gives a surplus by showing how to add column headers. Not that the other answers are bad, but this is a valid one too. – Marcel Jan 10 '14 at 12:31
  • 1
    @Marcel I must be reading both the question and answer wrong, because I was (also?) looking for a way to turn a list of "simple" values (i.e. `1,2,3,4`) into a grid with X columns, where each cell represents an item (`1` or `2` or `3`, etc) from the list. This just shows how to turn a list of "complex" values (i.e. `[{id:1, name:...}, {id:2, name:...}, ...]`) into a table where each _row_ represents an item, not a cell, and therefore doesn't answer the question. – drzaus Jan 13 '14 at 18:48
  • @drzaus Got it now, yeah - it answers my question, but not the OP's question. – Marcel Jan 14 '14 at 06:38
8
<asp:Repeater runat="server" DataSourceID="testds">
   <HeaderTemplate>
       <table class="items">
   </HeaderTemplate>
   <ItemTemplate>
       <%# (Container.ItemIndex + 3) % 3 == 0 ? "<tr>" : string.Empty%>
           <td><img src='/blablabla/<%# Eval("id") %>.jpg' alt="" /></td>
       <%# (Container.ItemIndex + 3) % 3 == 2 ? "</tr>" : string.Empty%>
   </ItemTemplate>
   <FooterTemplate>
       </table>
   </FooterTemplate>
</asp:Repeater>
Alexandr
  • 81
  • 1
  • 2
  • 3
    doesn't this fail to add row terminator with 1 item? should instead start/end row in header/footer template, then you only need to check index once and add `` if `Container.ItemIndex % 3 == 0 && Container.ItemIndex > 0` – drzaus Jan 30 '13 at 14:28
  • also, adding 3 to the index is redundant – drzaus Jan 30 '13 at 14:29
0

I am assuming you have all those name in 5 rows of data and you want to spread it across 3 columns in a repeater and not have 2 rows of data with 3 fields which would be straight forward. Based on my assumption your data is something like:

DataTable (or whatever your source is):

ID      Name
---------------
1       Bob
2       John
3       Joe
4       Mary
5       Mike

You can do it using a Repeater and a Literal with a little logic on the OnDataBinding event of the Literal.

First define your Repeater:

<asp:Repeater ID="repeater" runat="server">
    <HeaderTemplate>
        <table>
    </HeaderTemplate>
    <ItemTemplate>
        <asp:Literal ID="litItem" runat="server" OnDataBinding="litItem_DataBinding" />
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>

Next you will need a constant for the total columns you want and two global variables to track the binding operation. Define them like so:

public partial class _YourPage : System.Web.UI.Page
{
    private const int _repeaterTotalColumns = 3;
    private int _repeaterCount = 0;
    private int _repeaterTotalBoundItems = 0;

Then you will need to implement the OnDataBinding to do all the custom work:

protected void litItem_DataBinding(object sender, System.EventArgs e)
{
    Literal lt = (Literal)(sender);
    _repeaterCount++;            
    if (_repeaterCount % _repeaterTotalColumns == 1)
    {
        lt.Text = "<tr>";
    }

    lt.Text += string.Format("<td>{0}</td>", Eval("Name").ToString());

    if (_repeaterCount == _repeaterTotalBoundItems)
    {
        // Last item so put in the extra <td> if required
        for (int i = 0;
             i < (_repeaterTotalColumns - (_repeaterCount % _repeaterTotalColumns));
             i++)
        {
            lt.Text += "<td></td>";
        }
        lt.Text += "</tr>";
    }

    if (_repeaterCount % _repeaterTotalColumns == 0)
    {
        lt.Text += "</tr>";
    }
}

Then make sure when you bind your Repeater you are saving the total count:

 _repeaterTotalBoundItems = yourDataTable.Rows.Count;
 repeater.DataSource = yourDataTable;
 repeater.DataBind();

The output produced would be:

<table>    
<tr><td>Bob</td>
<td>John</td>
<td>Joe</td></tr>
<tr><td>Mary</td>
<td>Mike</td><td></td></tr>
</table>

You could probably improve the DataBinding code but I just rattled it off to give the basic premise of how to accomplish your goal. If the DataBinding needs to do a lot of string concat operations, you should probably switch to to using a StringBuilder and then just assign the Literal in the last operation.

Kelsey
  • 47,246
  • 16
  • 124
  • 162
0

Or just use a div in the repeater and then solve the hight/width issues with CSS.

MrTombola
  • 9
  • 1