Adding paging to a repeater

While the Gridview control has pagination built in, alot of the time, you may want to add pagination into your repeater control as well. Thankfully, ASP.NET has a PagedDataSource object to help accomplish this task.

* remember you must use a datatable/dataset to use pagination, a datareader cannot be used to accomplish this task

Basically, the PagedDataSource object will act as the middle tier between your data object and the binding to the repeater.

For the HTML, let’s just create the repeater and a label to display the current page
<asp:Repeater ID="repeater1" runat="server" >
<ItemTemplate>
<%# Eval("field") %>
</ItemTemplate>
</asp:Repeater>

<asp:Label id="lblCurrentPage" runat="server" />

For the code behind, make sure that all this code is in a method/sub routine for calling later.

C#
private void BindData()
{
string sql = "SELECT field FROM table";

SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["string"].ConnectionString);

conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataTable dt = new DataTable();
da.Fill(dt);

// Populate the repeater control with the Datatable
PagedDataSource objPds = new PagedDataSource();
objPds.DataSource = dt.DefaultView;

// Indicate that the data should be paged
objPds.AllowPaging = true;

// Set the pagesize
objPds.PageSize = 5;

int curpage;

if (ViewState["Page"] != null)
{
curpage = Convert.ToInt32(ViewState["Page"]);
}
else
{
ViewState["Page"] = 1;
curpage = 1;
}

// Set the currentindex
objPds.CurrentPageIndex = curpage - 1;

// Display the current page
lblCurrentPage.Text = "Page: " + (curpage).ToString() + " of " + objPds.PageCount.ToString();

// Bind the repeater
repeater1.DataSource = objPds;
repeater1.DataBind();
}

VB.Net
Private Sub BindData()
Dim sql as String = "SELECT field FROM table"

Dim conn As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("string").ConnectionString)

conn.Open()
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, conn)
Dim dt As DataTable = New DataTable()
da.Fill(dt)

' Populate the repeater control with the datatable
Dim objPds As PagedDataSource = New PagedDataSource()
objPds.DataSource = dt.DefaultView

' Indicate that the data should be paged
objPds.AllowPaging = True

' Set the pagesize
objPds.PageSize = 5

dim curpage as Integer

' we'll use ViewState to track the currentindex
If Not (ViewState("Page") Is Nothing) Then
curpage = Convert.ToInt32(ViewState("Page"))
Else
ViewState("Page") = 1
curpage = 1
End If

' Set the currentindex
objPds.CurrentPageIndex = curpage - 1

' Display the current page
lblCurrentPage.Text = "Page: " & (curpage).ToString() & " of " & objPds.PageCount.ToString()

' Bind the repeater
repeater1.DataSource = objPds
repeater1.DataBind()

End Sub

This should show you your repeater listing off the various fields with 5 records per page. You’ll notice a glaring problem, you can’t move from page to page! To do this, we need to add some paging controls

Add the following HTML below the label you created earlier
<asp:LinkButton id="lnkPrev" runat="server" text=" Previous " OnClick="lnkPrev_Click" />
<asp:LinkButton id="lnkNext" runat="server" text=" Next " OnClick="lnkNext_Click" />

Now we have to add the event handler for these Link buttons which will figure out the new page index, update the viewstate and rebind the repeater.

C#
protected void lnkPrev_Click(object sender, EventArgs e)
{
// Set viewstate variable to the previous page
ViewState["Page"] = Convert.ToInt32(ViewState["Page"]) - 1;

// reload the control
BindData();
}

protected void lnkNext_Click(object sender, EventArgs e)
{
// Set viewstate variable to the next page
ViewState["Page"] = Convert.ToInt32(ViewState["Page"]) + 1;

// reload the control
BindData();
}

VB.NET
Protected Sub lnkPrev_Click(ByVal sender As Object, ByVal e As EventArgs)
' Set viewstate variable to the previous page
ViewState("Page") = Convert.ToInt32(ViewState("Page")) - 1

' Reload control
BindData()
End Sub

Protected Sub lnkNext_Click(ByVal sender As Object, ByVal e As EventArgs)
' Set viewstate variable to the next page
ViewState("Page") = Convert.ToInt32(ViewState("Page")) + 1

' Reload control
BindData()
End Sub

That should do it, let me know if you have any questions!

11 Responses to "Adding paging to a repeater"

  1. David

    Very easy to implement. I’ve actually extended it further to provide navigation similar to a GridView such as First/Last options, a list of page number as well as a drop down to adjust the number of results per page.

  2. Desmond

    Hey…..can i know where You declare curpage and CurrentPageIndex?

    • Thanks for the catch Desmond, I had declared curpage in the C# code, but not in the VB.NET code. I’ve updated the example to show where it’s declared (basially right before it’s used)

      As for CurrentPageIndex, it’s a property of the PagedDataSource so no need to declare it.

  3. Soeren

    @David…

    How did you create the list of page numbers, and make it change according to the next/previous buttons? I’m trying to accomplish something similar, but I can’t quite make it work…

  4. david holley

    The first sub does the hard and fast work of creating the page numbers for the repeater. The second enables the linkbuttons to do their job. You’ll need to place a asp:panel on your page in the location where you want the index to appear as in
    . The code dynamically adds linkbuttons to this panel. Conceivably you could use images instead of linkbuttons if you have the digits 0-9 as images and then combine them as needed for the buttons.

    I also added a ‘Results Per Page’ drop down which simply required objPds.PageSize to be pointed to the drop down list as in
    ‘ Set the pagesize
    objPds.PageSize = NumberOfResultsPerPage.SelectedValue
    Setting the Autopostback property to true automatically updates the repeater.

    Public Sub CreateRepeaterPageMenu()

    Dim i As Integer
    Dim StartingPageNumber As Integer
    Dim EndingPageNumber As Integer
    Dim PageCount As Integer
    Dim ParentDivWidth As Integer
    Dim NewLinkButton As New LinkButton

    RepeaterPagesParent.Controls.Clear

    ‘Center the list of page numbers within its granparent div by dynamically adjusting the width as needed
    ‘Adjust if we’ll be adding in an option to show more or show less
    ’30 is the max number of Page Numbers to display
    ’22 is the width of each Page Nubmer’s div and factors in the 2px from the border around the div
    If RepeaterDirectoryPageCount < 26 Then
    StartingPageNumber = 1
    EndingPageNumber = RepeaterDirectoryPageCount
    ParentDivWidth = RepeaterDirectoryPageCount * 22
    Else
    PageCount = 25
    ParentDivWidth = 25 * 22
    If curpage = StartingPageNumber And curpage RepeaterDirectoryPageCount Then EndingPageNumber = RepeaterDirectoryPageCount
    End If
    End If

    If StartingPageNumber > 1 Then ParentDivWidth = ParentDivWidth + 22
    If RepeaterDirectoryPageCount – EndingPageNumber > 0 Then ParentDivWidth = ParentDivWidth + 22

    If StartingPageNumber > 1 Then
    NewLinkButton = New LinkButton
    With NewLinkButton
    .ID = “PageDown”
    .Text = “…”
    .CssClass = “RepeaterPageSelector”
    .CommandName = “SelectPage”
    .CommandArgument = StartingPageNumber – 1
    AddHandler NewLinkButton.Command, AddressOf SelectPage
    End With
    RepeaterPagesParent.Controls.Add(NewLinkButton)
    End If

    If RepeaterDirectoryPageCount > 1 Then
    For i = StartingPageNumber To EndingPageNumber
    ‘For the current page insert a Label and grey it out
    If i = curpage Then
    Dim NewAspLabel = New Label
    With NewAspLabel
    .ID = “SelectPage_” & i.ToString
    .Text = i.ToString
    .CssClass = “RepeaterPageSelectorCurrentPage”
    End With
    RepeaterPagesParent.Controls.Add(NewAspLabel)
    Else
    NewLinkButton = New LinkButton
    With NewLinkButton
    .ID = “SelectPage_” & i.ToString
    .Text = i.ToString
    .CssClass = “RepeaterPageSelector”
    .CommandName = “SelectPage”
    .CommandArgument = i
    AddHandler NewLinkButton.Command, AddressOf SelectPage
    End With
    RepeaterPagesParent.Controls.Add(NewLinkButton)
    End If
    Next
    End If
    ‘Add Leading elipse [...]
    If RepeaterDirectoryPageCount – EndingPageNumber > 0 Then
    NewLinkButton = New LinkButton
    With NewLinkButton
    .ID = “PageUp”
    .Text = “…”
    .CssClass = “RepeaterPageSelector”
    .CommandName = “SelectPage”
    .CommandArgument = StartingPageNumber + 25
    AddHandler NewLinkButton.Command, AddressOf SelectPage
    End With
    RepeaterPagesParent.Controls.Add(NewLinkButton)
    End If

    End Sub

    Public Sub SelectPage(ByVal sender As LinkButton, ByVal e As System.EventArgs)

    ‘ Set viewstate variable to the next page
    ViewState(“Page”) = sender.CommandArgument

    ‘ Reload control
    BindData()
    CreateRepeaterPageMenu()

    End Sub

    The following code when added to BIND() will dynamically hide/show the first, previous, next, last link buttons based on the number of records returned and the current page. It should be added after the .Databind() method is called.

    ‘Hide the First/Previous LinkButton or Next/Last LinkButton if we’re at the start or end of the records
    LnkFirst.Visible = True
    lnkPrev.Visible = True
    lnkLast.Visible = True
    lnkNext.Visible = True
    Select Case curpage
    Case 1
    LnkFirst.Visible = False
    lnkPrev.Visible = False
    If RepeaterDirectoryPageCount < 2 Then
    lnkLast.Visible = False
    lnkNext.Visible = False
    End If
    Case RepeaterDirectoryPageCount
    lnkLast.Visible = False
    lnkNext.Visible = False
    End Select

  5. david holley

    Forgot this bit…

    CreateRepeaterPageMenu() must be added to Bind() to recreate the page index each time that the page number is changed – whether by selecting the page specifically or using the navigation button.

  6. Al

    You made it so simple! Thank you for taking the time.

  7. Mel

    Hi there,

    I am having some problems where when I click next it doesn’t load the next set of items for some reason. I have used the code exactly the same as your example. Any ideas?

    Cheers,
    Mel

  8. jon

    THIS SAVED MY LIFE >> !! THANKS IT WORKS GREAT !!

  9. Vijay

    though i have written the code as mentioned step by step, i have got following errors:
    1. BindData() is not declared
    2.Name ‘lblCurrentPage’ is not declared.
    please explain the reason.

    • BindData not declared is strange as the whole method is included in the first code step. In C# “private void BindData()” and VB.NET “Private Sub BindData()”.

      lblCurrentPage is in the first step for the code on the aspx page “”

      Without seeing your code, I am not sure what the issue might be, please feel free to email to me and I can help out, otherwise, download the sample code at the end of the post

Leave a Reply