Extending DataPager: Creating a google analytics data pager

Author: Luis Ramirez.
March 25, 2008.

Download GooglePagerField webcontrol

The DataPager is one of the new webcontrols deployed with ASP.NET 3.5. The DataPager webcontrol allows you to add paging support for databound controls that implements the IPageableItemContainer interface. For example, you can use the DataPager webcontrol to give paging support to the new ListView webcontrol.

One of the things that seems more interesting about the DataPager webcontrol is the ability to extend its functionality with a new one that fits your needs best. Extending the DataPager webcontrol is exactly what we are going to do now. We are going to create a custom DataPager that gives a similar functionality than the pager found in Google analytics (see Figure 1).


Figure 1.

Google Analytics ASP.NET Grid Serie

The Google Analytics ASP.NET Grid Serie will show you how to create an ASP.NET Grid that recreates the appearance and behavior of the Grid displayed in the Google Analytics web site.

Understanding the DataPager webcontrol and DataPagerField

When you have a huge amount of data most of the times you don't want to display all the data at once. For performance and usability issues is better to display only a set of records and not all the records at once. The DataPager webcontrol allows you to split your data into pages and every time that a user select a page he will see the set of records corresponding to the selected page. For example, if you have 100 data records you can use the DataPager webcontrol to display only 10 records per page. The first page displays the records 1-10, the second page displays the records 11-20, and so on.

To start using the DataPager webcontrol you only need to drag and drop a DataPager webcontrol to your webform. The DataPager webcontrol has two paging styles by default:

  • Numeric style (NumericPagerField): Allows the user to browse a set of records selecting a page number.

    Figure 2.
  • Next and previous style (NextPreviousPagerField): Allows the user to browse a set of records selecting the first, previous, next and last page.

    Figure 3.

If you want to use the numeric style to page your data you need to add the NumericPagerField to the Fields collection of the DataPager webcontrol.

1<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1"> 2 <Fields> 3 <asp:NumericPagerField /> 4 </Fields> 5 </asp:DataPager>

If you want to use the next and previous style to page your data you need to add the NextPreviousPagerField to the Fields collection of the DataPager webcontrol.

1<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1"> 2 <Fields> 3 <asp:NextPreviousPagerField /> 4 </Fields> 5 </asp:DataPager>

The DataPager webcontrol actually doesn't render the appearance neither of the numeric style nor of the next and previous style. The NumericPagerField and NextPreviousPagerField classes handle the rendering of the numeric and the next and previous style, respectively.

The NumericPagerField and the NextPreviousPagerField classes are known as navigation controls, both derive from the . If you want to create a custom appearance and functionality for the DataPager control then you can use the TemplatePagerField class or you can create a custom navigation control. For the purpose of this article we will create our own navigation control for the DataPager webcontrol.

GooglePagerField: Google analytics navigation control

Now we are going to talk about our navigation control, the GooglePagerField. The GooglePagerField allows you to specify the first record to be displayed, set the maximum number of records displayed per page and move to the previous and next page.


Figure 4.

Extending DataPagerField

Now is time to create our Google data pager navigation control. We are not going to extend the DataPager class, what we are going to do is to extend the DataPagerField class. The DataPagerField class provides the basic functionality of a navigation control.

I we want to extend the DataPagerField class we need to implement the functionality of the CreateField, CreateDataPagers and HandleEvent methods.

1public class GooglePagerField : DataPagerField 2{ 3 protected override DataPagerField CreateField() 4 { 5 } 6 7 public override void CreateDataPagers(DataPagerFieldItem container, int startRowIndex, int maximumRows, 8 int totalRowCount, int fieldIndex) 9 { 10 } 11 12 public override void HandleEvent(CommandEventArgs e) 13 { 14 } 15}

CreateField method

Returns an instance of the GooglePagerField class.

1protected override DataPagerField CreateField() 2{ 3 return new GooglePagerField(); 4}

CreateDataPagers method

Creates the UI for our data pager. The table 1 explains the meaning of the parameters of the CreateDataPagers method.

container An instance that implements the INamingContainer interface. The DataPagerFieldItem instance is used to build a unique identifier for the controls created in the CreateDataPagers method.
startRowIndex Specify the index of the data row that will be displated at the beginning.
maximumRows Specify the maximum number of data rows that will be displayed by page. For example, if you have a datasource with 100 records you may specify that 10 records per page will be displayed by maximum.
totalRowCount Specify the total data rows that your datasource has. For example, 100 records.
fieldIndex Specify the position of our GooglePagerField within the fields collection of the DataPager webcontrol.

Table 1.

The CreateDataPagers method creates the UI that will be displayed to the user. The CreateDataPagers method checks whether to render the UI using the values returned by the event raised by a user action or using the values passed in the query string of the ASPX webform.

1public override void CreateDataPagers(DataPagerFieldItem container, int startRowIndex, int maximumRows, 2 int totalRowCount, int fieldIndex) 3{ 4 this._startRowIndex = startRowIndex; 5 this._maximumRows = maximumRows; 6 this._totalRowCount = totalRowCount; 7 8 if (string.IsNullOrEmpty(base.DataPager.QueryStringField)) 9 { 10 this.CreateDataPagersForCommand(container, fieldIndex); 11 } 12 else 13 { 14 this.CreateDataPagersForQueryString(container, fieldIndex); 15 } 16}

The CreateDataPagersForCommand method creates the controls used to give the functionality to our GooglePagerField.

1private void CreateDataPagersForCommand(DataPagerFieldItem container, int fieldIndex) 2{ 3 //Goto item texbox 4 this.CreateGoToTexBox(container); 5 6 //Control used to set the page size. 7 this.CreatePageSizeControl(container); 8 9 //Set of records - total records 10 this.CreateLabelRecordControl(container); 11 12 //Previous button 13 if (this._showPreviousPage) 14 { 15 container.Controls.Add(this.CreateControl("Prev", this.PreviousPageText, fieldIndex, 16 this.PreviousPageImageUrl, this._showPreviousPage)); 17 this.AddNonBreakingSpace(container); 18 } 19 20 //Next button 21 if (this._showNextPage) 22 { 23 container.Controls.Add(this.CreateControl("Next", this.NextPageText, fieldIndex, 24 this.NextPageImageUrl, this._showNextPage)); 25 this.AddNonBreakingSpace(container); 26 } 27}

HandleEvent method

Handles the events raised by the objects created in the CreateDataPagers method. The table 3 shows you the commands handled by the HandleEvent method.

UpdatePageSize This command occurs when the user select an item in the 'Show rows' dropdown list.
GoToItem This command occurs when the user specify a value in the 'Go to' textbox and press enter.
Prev This command occurs when the user select the previous page button.
Next This command occurs when the user select the next page button.
1public override void HandleEvent(CommandEventArgs e) 2{ 3 if (string.Equals(e.CommandName, "UpdatePageSize")) 4 { 5 base.DataPager.PageSize = Int32.Parse(e.CommandArgument.ToString()); 6 base.DataPager.SetPageProperties(this._startRowIndex, base.DataPager.PageSize, true); 7 return; 8 } 9 10 if (string.Equals(e.CommandName, "GoToItem")) 11 { 12 int newStartRowIndex = Int32.Parse(e.CommandArgument.ToString()); 13 base.DataPager.SetPageProperties(newStartRowIndex, base.DataPager.PageSize, true); 14 return; 15 } 16 17 if (string.IsNullOrEmpty(base.DataPager.QueryStringField)) 18 { 19 if (string.Equals(e.CommandName, "Prev")) 20 { 21 int startRowIndex = this._startRowIndex - base.DataPager.PageSize; 22 if (startRowIndex < 0) 23 { 24 startRowIndex = 0; 25 } 26 base.DataPager.SetPageProperties(startRowIndex, base.DataPager.PageSize, true); 27 } 28 else if (string.Equals(e.CommandName, "Next")) 29 { 30 int nextStartRowIndex = this._startRowIndex + base.DataPager.PageSize; 31 32 if (nextStartRowIndex > this._totalRowCount) 33 nextStartRowIndex = this._totalRowCount - base.DataPager.PageSize; 34 35 if (nextStartRowIndex < 0) 36 nextStartRowIndex = 0; 37 38 base.DataPager.SetPageProperties(nextStartRowIndex, base.DataPager.PageSize, true); 39 } 40 } 41}

ButtonDropDownList webcontrol

The ButtonDropDownList is a custom dropdownlist webcontrol created to allow the user to select the page size. The ButtonDropDownList webcontrol implements the IPostBackEventHandler. The IPostBackEventHandler allows to the ButtonDropDownList webcontrol to raise a Command event which can be handled by the GooglePagerField class.

1public class ButtonDropDownList : DropDownList, IPostBackEventHandler 2{ 3}

The RaisePostBackEvent method raises the command event which is handled by the HandledEvent method of the GoogleDataPagerField class. The selected page size is passed as the event argument.

1void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) 2{ 3 this.CommandArgument = "0"; 4 5 if (base.SelectedItem != null) 6 this.CommandArgument = this.SelectedItem.Value; 7 8 this.RaisePostBackEvent(eventArgument); 9} 10 11protected virtual void RaisePostBackEvent(string eventArgument) 12{ 13 if (this.CausesValidation) 14 { 15 this.Page.Validate(this.ValidationGroup); 16 } 17 this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument)); 18} 19 20protected virtual void OnCommand(CommandEventArgs e) 21{ 22 CommandEventHandler handler = (CommandEventHandler)base.Events[EventCommand]; 23 if (handler != null) 24 { 25 handler(this, e); 26 } 27 //It bubbles the event to the HandleEvent method of the GoogleDataPagerField class. 28 base.RaiseBubbleEvent(this, e); 29}

ButtonTextBox webcontrol

The ButtonTextBox is a custom textbox webcontrol created to allow the user to display the data records beginning at the specified record. The ButtonTextBox webcontrol implements the IPostBackEventHandler. The IPostBackEventHandler allows to the ButtonTextBox webcontrol to raise a Command event which can be handled by the GooglePagerField class.

1public class ButtonTextBox : TextBox, IPostBackEventHandler 2{ 3}

The RaisePostBackEvent method raises the command event which is handled by the HandledEvent method of the GoogleDataPagerField class. The specified record is passed as the event argument.

1void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) 2{ 3 this.CommandArgument = base.Text; 4 this.RaisePostBackEvent(eventArgument); 5}

Using the GoogleDataPagerField

To use the Google data pager in your web applications you only need to add a GoogleDataPagerField to the fields collection of the DataPager class.

1<asp:ListView ID="ListView1" runat="server" DataSourceID="AccessDataSource1" ItemPlaceholderID="itemPlaceHolder"> 2<LayoutTemplate> 3<table class="tableInfo"> 4 <tr> 5 <th>ID</th> 6 <th>First name</th> 7 <th>Last name</th> 8 </tr> 9 <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder> 10 <tr> 11 <td colspan="3"> 12 <asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1" PageSize="5" > 13 <Fields> 14 <SqlNetFrameworkWebControls:GooglePagerField 15 NextPageImageUrl="~/Images/button_arrow_right.gif" 16 PreviousPageImageUrl="~/Images/button_arrow_left.gif" /> 17 </Fields> 18 </asp:DataPager> 19 </td> 20 </tr> 21</table> 22</LayoutTemplate> 23<ItemTemplate> 24 <tr> 25 <td><%# Eval("PlayerId") %></td> 26 <td><%# Eval("FirstName") %></td> 27 <td><%# Eval("LastName") %></td> 28 </tr> 29</ItemTemplate> 30</asp:ListView>

Conclusion

The DataPager webcontrol separates the paging functionality from the databound webcontrol. It allows you to have the freedom to customize the paging appearance and functionality to your own needs.