Monday, July 23, 2007

Creating a PagerTemplate for the GridView Control

When you retrieve a lot of data from a datasource that will be displayed on the page by using the GridView control, you probably don't want to show every row on a single page, especially not when you have hundreds of rows. Displaying hundreds of rows on a single page will use a lot of resources, both on the server and the client. Every row rendered by the GridView contains a set of rendered HTML elements; those will be sent over the network to the browser. If you have several rows that should be displayed, more data will be sent to the client and more bandwidth is required. To minimize the numbers of rows to be displayed on a page, you can use the GridView's paging feature, which will display rows in pages. You can specify how many rows one page will display, and to switch pages you can click a Next button or the number of the page to switch to. Using paging minimizes the data sent over the network and makes it easier for the user to navigate the data. To enable paging, you set the GridView's AllowPaging property to true. When this is done, an additional row called the pager row is automatically displayed in the GridView control. The pager row can be located at the top or the bottom of the GridView control, or both at the top and the bottom of the GridView control. To specify the number of rows that should be displayed on each page, you can use the GridView's PageSize property; by default the value is set to 10, which means that 10 rows will be displayed on each page.

By using the PagerSettings property of the GridView, you can specify how a user switches to another page. You can, for example, specify that you want to use a Preview and Next button, First and Last buttons, and a numeric list, with the number of each page. The user can click the number to move to a specific page. The GridView control only supports a way to specify how the paging row of the GridView should look. You can, for example, use a drop-down list with the number of pages the users can switch to, or use the Previous and Next buttons together with a numeric list. (The GridView doesn't support this currently.) You can create your own pager template to specify exactly how you want the user to switch to another page. To specify your own paging template, you can use the PagerTemplate of the GridView control. The following example uses the PagerTemplate of the GridView to display the selected page and the number of total pages. It also displays Next and Preview buttons for moving between pages:

AllowPaging="True"
Id="GridView1"
...>

Selected Index <%= GridView1.PageIndex * GridView1.PageSize %>
Number of pages <%=GridView1.PageCount %>
CommandName="Page"
CommandArgument="Prev"

Text="Preview" ...>
CommandName="Page"
CommandArgument="Next"
Text="Next" ..>



The whole code example in which the PagerTemplate is used can be found in the file pager1.aspx of the examples files for this chapter, which can be downloaded from http://www.wrox.com.

By using a server-side code block within the template, you can create your own pager. If you want to add a First/Last or Next/Prev button, you simply add a Button control and set its CommandName to Page and the CommandArgument to First, Last, Next, or Prev. You don't need to add any event to handle the paging; the GridView gets the CommandArgument for the buttons you have selected and does the action for you automatically. To add numeric paging, you add Button controls with the CommandName set to Page and the CommandArgument set to the index of the page to navigate to.

You can also programmatically manipulate the top or bottom paging row by using the TopPagerRow or BottomPagerRow property of the GridView control. As you probably have guessed based on the name, the TopPagerRow accesses the pager row located at the top (if you specify rendering the paging control at the top of the GridView) and the BottomPagerRow is the paging control located at the bottom of the GridView. The TopPagerRow and BottomPagerRow are of type GridViewRow. The important thing to remember when you decide to manipulate TopPagerRow or BottomPagerRow is that the manipulation must be performed after the GridView control has been rendered. If you do it before, the changes will be overwritten by the GridView control. A good place to manipulate the pager row is to hook up to the GridView's DataBound event. Listing 7-2 uses the PagerTemplate where a DropDownList control is added, and where the DropDownList control's items represent each page to which a user can navigate. BottomPagerRow is used to manipulate the pager row.

Listing 7-2: Using PagerTemplate with a DropDownList control


<%@ Page language="C#" %>







datasourceid="CustomersSqlDataSource"
ondatabound="CustomersGridView_DataBound"
autogeneratecolumns="true"
allowpaging="true"

runat="server"
pageSize=15>














id="ViewPageLabel"
text="View page:"
runat="server"/>

autopostback="true"
onselectedindexchanged="PageDropDownList_SelectedIndexChanged"
runat="server"/>









id="CustomersSqlDataSource"
connectionstring="<%$ ConnectionStrings:NorthWindConnectionString%>"
selectcommand="Select [CustomerID], [CompanyName], [Address], [City],
[PostalCode], [Country] From [Customers]"
runat="server">









The source code to this example can found in the file pager2.aspx.

The example here uses the Northwind database to get a list of customers from the Customers table.

Let's split the code into pieces and take a look at it in more detail. The example uses a pagerTemplate to specify a custom pager row for the GridView. The pagerTemplate has a table with two columns; the first column has a DropDownList control with the id PageDropDownList. This is where the number of pages a user can select will be added. The other column represents information about which page a user has selected.













id="ViewPageLabel"
text="View page:"
runat="server"/>

id="PageDropDownList"
autopostback="true"
onselectedindexchanged="PageDropDownList_SelectedIndexChanged"
runat="server"/>








PagerDropDownList has the AutoPostBack attribute set to true, and when a user selects a page to view, the PageDropDownList_SelectedIndexChanged event is triggered.

void PageDropDownList_SelectedIndexChanged(Object sender, EventArgs e)
{
GridViewRow bottomPagerRow = CustomersGridView.BottomPagerRow;

DropDownList pageList =
bottomPagerRow.Cells[0].FindControl("PageDropDownList") as DropDownList;

if (pageList != null)
CustomersGridView.PageIndex = pageList.SelectedIndex;
}

PageDropDownList_SelectedIndexChanged uses the BottomPagerRow property of the GridView (CustomerGridView) control to get the GridViewRow that represents the content of the pagerTemplate. To get the PageDropDownList from pagerTemplate, the FindControl method is used. If the PageDrop DownList is found within the GridViewRow cells, the GridView's PageIndex property will be set to the selected index of the PageDropDownList. The index of the selected items in the DropDownList represents the index of the page to be displayed. The PageIndex property of the GridView is used to specify which page a user will see.

Because the manipulation of the pager row must be done after the GridView is rendered, the GridView's DataBound event is used to manipulate the pager row. If the manipulation takes place before the Grid View is rendered, the GridView will reset the manipulation. The DataBound event is triggered after the data is bound to the DataGrid:


id="CustomersGridView"
ondatabound="CustomersGridView_DataBound"
...>

The CustomersGridView_DataBound method is triggered when the GridView's DataBound event is triggered:

void CustomersGridView_DataBound(Object sender, EventArgs e)
{
// Retrieve the pager row.
GridViewRow pagerRow = CustomersGridView.BottomPagerRow;

// Retrieve the DropDownList and Label controls from the row.
DropDownList pageList = pagerRow.Cells[0].FindControl("PageDropDownList")
as DropDownList;

Label pageLabel = pagerRow.Cells[0].FindControl("SelectedPageLabel") as
Label;

The CustomerGridView_DataBound method will get the GridViewRow that represents the pager row from the GridView by using the GridView's BottomPagerRow. In this method, the pages that a user can select will be added to the PageDropDownList inside the GridView's pagerTemplate. FindControl is used to get the PageDropDownList from the BottomPagerRow. There is also a Label control—SelectedPage Label—added to the pager row which represents the current page that is selected.

To get the number of pages in which the datasource is split, you can use the PageCount property of the GridView:

if(pageList != null)
{
//Add the number of pages to the ListBox
for (int i=0; i {
int pageNumber = i + 1;

//Create a ListItem that represents a page
ListItem item = new ListItem(pageNumber.ToString());

To fill the DropDownList in the pager row with the pages a user can navigate to, a for loop is used. The for loop starts from zero and goes to the number of pages into which the data is split. Because the text of the items in the DropDownList should start from one and not from zero, 1 is added to the current index of the for loop and put into a new variable that represents the text the ListItem in the DropDownList will have. A new ListItem is created to be added to the DropDownList later in the code.

When a user selects a page to view from the drop-down list, the current page item in the drop-down list should be selected. That can be done by getting the current index the GridView is displaying by using the PageIndex property of the GridView control:

//If a page is already selected, make sure the
//ListBox selects the selected page
if (i==CustomersGridView.PageIndex)
item.Selected = true;

// Add the ListItem object to the Items collection of the
// DropDownList.
pageList.Items.Add(item);

If the current index of the for loop (used to add an item to DropDownList) is equal to the GridView's PageIndex, the current created item has its Selected property set to true. The Selected property of the ListItem is a marker to tell the DropDownList which item should be selected by default.

The last thing the code example in this topic does is set the Label control inside the pager row to display which page a user has selected, and the number of total pages from which a user can select:

// Get the current page number.
int currentPage = CustomersGridView.PageIndex + 1;

pageLabel.Text = "Page " + currentPage.ToString() +
" of " + CustomersGridView.PageCount.ToString();

To get the total number of pages into which the data returned from the datasource is split, you use the PageCount property of the GridView.

In this section, you learned how to use the pagerTemplate of the GridView control to create and define your own template for the GridView's pager feature. You also learned how to use the BottomPagerRow to manipulate the pager row dynamically with code, and that the manipulation of the pager row must be done after the GridView is rendered.

No comments: