When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, February 13, 2008

Using ASP.NET 3.5's ListView and DataPager Controls: Paging Through Data with the ListView and DataPager Controls

By Scott Mitchell


A Multipart Series on ASP.NET's ListView and DataPager Controls
This article is one in a series of articles on ASP.NET's ListView and DataPager controls, which were introduced with ASP.NET version 3.5.

  • Displaying Data with the ListView - looks at the ListView control basics, with demos on how to display data using the LayoutTemplate and ItemTemplate.
  • Grouping Data with the ListView Control - shows how to render different formatting or encasing markup to every N rendered records.
  • Sorting Data with the ListView Control - shows how to include buttons to sort the ListView's data.
  • Paging Through Data with the ListView and DataPager Controls - shows how to page through the ListView's data using the DataPager control.
  • Grouping By a Data Field - learn how to group the data in a ListView based on the actual data coming from the database.
  • Deleting Data - see how to delete the data bound to the ListView control.
  • Editing Data - learn how to edit the data bound to the ListView control.
  • Inserting Data - explore inserting new records directly from within the ListView control's interface.
  • Creating an SEO-Friendly Paging Interface - learn how to configure the DataPager to render an SEO-friendly paging interface.
  • The Ultimate DataPager Interface - create the ultimate DataPager interface using ASP.NET Routing.
  • Introduction


    The GridView, DetailsView, and FormView controls all support out of the box paging support that can be enabled at the tick of a checkbox. When configured to enable paging, these controls automatically render a paging interface comprised of LinkButtons, Buttons, or ImageButtons. The particular paging interface configuration - whether Next/Previous links are used, whether numeric paging options are used, the text displayed in the various buttons, and so on - are customizable through the data Web controls' properties. While these configuration options are nice, they only allow for a small amount of customization. For instance, the configuration options let you specify if you want the paging interface to appear at the top or bottom of the control (or in both locations). But if you want the paging interface to appear elsewhere on the page, separate from the paging interface, you're out of luck.

    The ASP.NET team remedied this problem with the ListView control by decoupling paging support from the ListView control and moving it to a separate, stand-along control, the DataPager. The DataPager control's sole purpose is to render a paging interface and communicate to its corresponding ListView control once the user interacts with the interface (such as choosing to move to the last page of data). This explicit separation between the ListView and DataPager allow for a much greater degree of paging interface customization and positioning, as we will se in this article.

    Read on to learn more!

    - continued -

    Paging Basics


    The DataPager control implements paging through three bits of information:
    • PagedControlID - the ID of the ListView control that the DataPager is generating the paging interface for.
    • StartRowIndex - the index of the first record to display in the current page
    • MaximumRows - the maximum number of rows to display per page
    For example, to display the first page of data when showing 10 records per page, these StartRowIndex and MaximumRows values would be 0 and 10, respectively. To show the second page of data, the values would be 10 and 10. To show the third, they'd be 20 and 10. There's also the read-only TotalRowCount property, which returns the total number of records being paged through.

    The DataPager control renders a set of DataPagerFields, with each DataPagerField displaying a paging interface. There .NET Framework version 3.5 includes three pre-built DataPagerFields: NextPreviousPagerField, NumericPagerField, and TemplatePagerField. The NextPreviousPagerField displays First/Previous/Next/Last buttons; NumericPagerField displays a series of page numbers; TemplatePagerField creates the paging interface via a template, that we must create.

    When a user interacts with the paging interface - by clicking the Next button, perhaps - a postback occurs and the DataPagerField recognizes that the event was caused by one of its paging user interface elements. The DataPagerField then determins the new StartRowIndex and MaximumRows values and passes them to the DataPager class's SetPageProperties method. The DataPager then calls its associated ListView control's SetPageProperties method, which causes the ListView to rebind to its data source and display just the appropriate subset of records.

    Default Paging vs. Custom Paging
    The ListView and DataPager controls offer two paging models: default paging and custom paging. The two models provide a tradeoff between performance and ease of setting up/configuring/using. The SqlDataSource control uses default paging; the ObjectDataSource uses default paging by default, but has an easy mechanism to indicate that it should use custom paging. Keep in mind that the ListView merely displays data; it's the data source control that is actually retrieving data from the database.

    With default paging, each time a new page of data in displayed, all of the data is requeried from data source control. Once all of the data has been returned, the ListView selectively displays part of the entire set of data, based on the StartRowIndex and MaximumRows values.

    With custom paging, you, the developer, have to do a bit more work. Rather than just being able to blindly bind the ListView to a data source control and add a DataPager control, you have to configure the data source control to selectively retrieve only those records that should be shown for the particular page.

    For more information on default and custom paging, and performance and implementation tradeoffs, see Custom Paging in ASP.NET with SQL Server 2005.

    Creating the DataPager and Defining its DataPagerFields


    Implementing paging with the ListView and DataPager controls isn't as easy as checking a checkbox, but it's not much more difficult. The download at the end of this article includes two DataPager tutorials, which we will discuss in the remainder of this article. These demos build upon the SimpleListView.aspx demo discussed in Displaying Data with the ListView.

    To start, add and configure the ListView control so that it displays data in the format you want. Then, to add paging, add one or more DataPager controls to the page, placing them wherever you want the paging interface to appear. The DataPager may appear within the ListView's LayoutTemplate or elsewhere on the page, outside of the control.

    After adding the DataPager, it will appear in the Visual Studio Design view as a gray box, as we have yet to indicate what DataPagerField(s) to use. To customize the DataPagerFields, click the Edit Pager Fields link from the DataPager's smar tag. This brings up the Fields dialog box (shown below). From here you can specify what DataPagerFields to add and their assorted properties. In the Fields dialog box below, I have added a NextPreviousPagerField and set the ButtonType property to Button (so that it displays the paging interface as Button controls, rather than using the default LinkButtons), and the ShowFirstPageButton and ShowLastPageButton properties to True so that they will be included along with the Next and Previous buttons.

    The Fields dialog box.

    After clicking OK to close the Fields dialog box, the DataPager's declarative markup updates to include the DataPagerField information; furthermore, the Designer shows the paging interface as First/Previous/Next/Last buttons.

    There are two more DataPager properties to set before we're ready to test this page. We need to specify what ListView the DataPager operates on. To accomplish this, set the DataPager's PagedControlID property to the ID of the ListView on the page. Next, set the DataPager's PageSize property to indicate how many records the ListView should show per page (the default value is 10). After making these changes, your DataPager's declarative markup should look similar to the following:

    <asp:DataPager ID="ProductListPagerSimple" runat="server"
       PagedControlID="ProductList" PageSize="5">
       <Fields>
          <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True"
                      ShowLastPageButton="True" />
       </Fields>
    </asp:DataPager>

    With this paging interface in place, visit the page through a browser. As the following screen shot shows, the ListView only displays 5 records per page (because the DataPager's PageSize property is set to 5). Moreover, the First and Previous buttons are disabled because we are viewing the first page of data.

    The ListView shows only five products per page.

    The paging interface in the screen shot above is displayed right above the ListView data. But keep in mind that a single ListView can include multiple DataPager controls. We could augment the paging interface to also appear at the bottom of the ListView by simply adding an additional DataPager control beneath the ListView and setting its PagedControlID and PageSize properties to the same values as the other DataPager control.

    Specifying Multiple DataPagerFields in the DataPager


    The previous example shows using a single DataPagerField in a DataPager (namely, a NextPreviousPagerField). The DataPager is flexible enough to allow for multiple DataPagerFields. This flexibility allows us to create hybrid paging interfaces, such as a paging interface with numeric pages and First and Last buttons.

    To create such an interface, add a DataPager to the page and set its PagedControlID and PageSize properties. Then bring up the Fields dialog box and add three DataPagerFields: a NextPreviousPagerField followed by a NumericPagerField followed by a NextPreviousPagerField. Configure the first NextPreviousPagerField's properties so that only the First button is shown; likewise, configure the last NextPreviousPagerField's properties so that only the Last button is shown. Feel free to also configure the text displayed in the First and Last buttons - I used << for the First button and >> for Last.

    <asp:DataPager ID="ProductListPagerCombo" runat="server"
       PagedControlID="ProductList" PageSize="5">
       <Fields>
          <asp:NextPreviousPagerField FirstPageText="&lt;&lt;" ShowFirstPageButton="True"
                 ShowNextPageButton="False" ShowPreviousPageButton="False" />
          <asp:NumericPagerField />
          <asp:NextPreviousPagerField LastPageText="&gt;&gt;" ShowLastPageButton="True"
                 ShowNextPageButton="False" ShowPreviousPageButton="False" />
       </Fields>
    </asp:DataPager>

    The net result is a hybrid paging interface, as illustrated in the screen shot below. Note that this page has two DataPagers. The one at the top is the First/Previous/Next/Last added from the previous example. The one at the bottom is the hybrid one.

    A hybrid paging interface is displayed.

    Creating a Custom Paging Interface with the TemplatedPagerField


    If neither the NumericPagerField nor NextPreviousPagerField meet your paging interface requirements, you can create a custom paging interface using the TemplatedPagerField. With this field, you, the page developer, are on the hook for creating the paging interface, detecting when the user interacts with the paging interface, and updating the DataPager and ListView in response.

    Let's create a paging interface that enumerates the available pages as ListItems in a DropDownList control, allowing the user to jump to a particular page by selecting the page number from the list. To achieve this, add a DataPager control to the page and configure its DataPagerFields, adding a TemplatedPagerField. The content for the template can be defined directly in the markup or through the Edit Templates option in the DataPager's smart tag. In either case, add a DropDownList control to the template. Set its ID to PageJump and set its AutoPostBack property to True.

    Our next task is to populate the DropDownList with the various pages. Because this needs to happen each time the ListView is bound to its data source, create an event handler for the ListView control's DataBound event and add the following code:

    Protected Sub ProductList_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles ProductList.DataBound
       Dim currentPage As Integer = (DataPagerID.StartRowIndex / DataPagerID.PageSize) + 1
       Dim totalPages As Integer = DataPagerID.TotalRowCount / DataPagerID.PageSize

       'Populate the DropDownList if needed
       Dim ddl As DropDownList = CType(DataPagerID.Controls(0).FindControl("PageJump"), DropDownList)
       If ddl.Items.Count = 0 Then
          'Add a list item for each page
          For i As Integer = 1 To totalPages
             ddl.Items.Add(i.ToString())
          Next

          'Set the DDL to the appropriate page value
          ddl.Items.FindByValue(currentPage.ToString()).Selected = True
       End If
    End Sub

    The code starts by computing the current page being viewed as well as how many total pages. This information is gleamed from the DataPager's StartRowIndex, PageSize, and TotalRowCount properties.

    Next, the PageJump DropDownList is programmatically referenced. Note that in order to reference the controls within the TemplatePagerField we need to use the rather esoteric code: DataPagerID.Controls(0).FindControl("controlID"). For some reason, there's no property for the DataPager control or its TemplatePagerField that allows access to the template's rendered contents. Therefore we have to hack it by working directly through the Controls collection. Ick.

    A loop enumerates the page numbers (from 1 to totalPages) and adds a ListItem for each page. Finally, the current page's corresponding DropDownList item is selected.

    If you visit the page at this time you'll see that the DataPager interface includes a DropDownList with a ListItem for each page. Moreover, selecting a different item from the list causes a postback, but the data displayed isn't changed. This is because we've yet to handle the DropDownList's SelectedIndexChanged event - it's here where we need to call the DataPager's SetPageProperties method, passing it the new StartRowIndex and MaximumRows values, so that it will update its ListView control's display.

    Creating an event handler for a control within a template requires adding the OnEventName=EventHandler syntax to the control's declarative markup. This can be entered by hand or, alternatively, can be auto-created by going to the Edit Templates view and double-clicking the DropDownList. In either case, once the event handler is created add the following code:

    Protected Sub PageJump_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
       Dim PageJumpDDL As DropDownList = CType(sender, DropDownList)
       Dim pageNo As Integer = Convert.ToInt32(PageJumpDDL.SelectedValue)

       Dim startRowIndex As Integer = (pageNo - 1) * ProductListPager.PageSize

       DataPagerID.SetPageProperties(startRowIndex, DataPagerID.PageSize, True)
    End Sub

    The above code starts by programmatically referencing the PageJump DropDownList control in order to ascertain its SelectedValue. This requested page number is used to calculate the StartRowIndex, and this information (and the DataPager's PageSize) are passed into the DataPager's SetPageProperties method.

    The net result is a DropDownList that lists each page number. Changing the selection causes a postback and displays the selected page of data.

    A custom paging interface is used.

    Conclusion


    Unlike its predecessors, the ListView does not intuitively support paging. Instead, the paging interface has been moved to a separate Web control, the DataPager. The DataPager's interface is rendered by its DataPagerFields. The .NET Framework ships with three built-in DataPagerFields: NextPreviousPagerField, NumericPagerField, and TemplatePagerField. In this article we looked at using all three fields.

    Happy Programming!

  • By Scott Mitchell


    Further Readings:

  • Displaying Data with the ListView
  • Paging and Sorting GridView Tutorials
  • Custom Paging in ASP.NET with SQL Server 2005
  • Attachments


  • Download the Demo (in ZIP format)


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article