Google Analytics ASP.NET Grid series
The Google Analytics ASP.NET Grid Series will show you how to create an ASP.NET grid that recreates the appearance and behavior of the grid displayed in the Google Analytics website.
Read the original article here.
Introduction
The DataPager
is one of the newest web controls deployed with ASP.NET 3.5. The DataPager
web control allows you to add paging support for data-bound controls that implement the IPageableItemContainer
interface. For example, you can use the DataPager
web control to give paging support to the new ListView
web control.
One of the things that seems more interesting about the DataPager
web control is the ability to extend its functionality with a new one that fits your needs best. Extending the DataPager
web control is exactly what we are going to do now. We are going to create a custom DataPager
that gives a similar functionality to the pager found in the Google Analytics website (see Figure 1).

Figure 1.
Understanding the DataPager web control 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, it is better to display only a set of records and not all the records at once. The DataPager
web control allows you to split your data into pages, and every time that a user selects 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
web control 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
web control, you only need to drag and drop a DataPager
web control to your web form. The DataPager
web control has two paging styles by default:
- Numeric style (
NumericPagerField
): Allows the user to browse a set of records by selecting a page number. 
Figure 2.
- Next and previous style (
NextPreviousPagerField
): Allows the user to browse a set of records by selecting the first, previous, next, and the last page. 
Figure 3.
If you want to use the numeric style to page your data, you need to add NumericPagerField
to the Fields
collection of the DataPager
web control.
<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1">
<Fields>
<asp:NumericPagerField />
</Fields>
</asp:DataPager>
If you want to use the next and previous style to page your data, you need to add NextPreviousPagerField
to the Fields
collection of the DataPager
web control.
<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1">
<Fields>
<asp:NextPreviousPagerField />
</Fields>
</asp:DataPager>
The DataPager
web control actually doesn't render the appearance of the numeric style or of the next and previous style. The NumericPagerField
and NextPreviousPagerField
classes handle the rendering of the numeric and the next and previous styles, respectively.
The NumericPagerField
and the NextPreviousPagerField
classes are known as navigation controls. 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 purposes of this article, we will create our own navigation control for the DataPager
web control.
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 pages.

Figure 4.
Extending the DataPagerField
Now is the 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 extend the DataPagerField
class. The DataPagerField
class provides the basic functionality of a navigation control. If we want to extend the DataPagerField
class, we need to implement the functionality of the CreateField
, CreateDataPagers
, and HandleEvent
methods.
public class GooglePagerField : DataPagerField
{
protected override DataPagerField CreateField()
{
}
public override void CreateDataPagers(DataPagerFieldItem container,
int startRowIndex, int maximumRows, int totalRowCount, int fieldIndex)
{
}
public override void HandleEvent(CommandEventArgs e)
{
}
}
CreateField method
Returns an instance of the GooglePagerField
class:
protected override DataPagerField CreateField()
{
return new GooglePagerField();
}
CreateDataPagers method
Creates the UI for our data pager. This table 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 | Specifies the index of the data row that will be displayed at the beginning. |
maximumRows | Specifies the maximum number of data rows that will be displayed by the page. For example, if you have a data source with 100 records, you may specify that 10 records per page will be displayed at the maximum. |
totalRowCount | Specifies the total data rows that your data source has. For example, 100 records. |
fieldIndex | Specifies the position of our GooglePagerField within the Fields collection of the DataPager web control. |
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 web form.
public override void CreateDataPagers(DataPagerFieldItem container, int startRowIndex,
int maximumRows, int totalRowCount, int fieldIndex)
{
this._startRowIndex = startRowIndex;
this._maximumRows = maximumRows;
this._totalRowCount = totalRowCount;
if (string.IsNullOrEmpty(base.DataPager.QueryStringField))
{
this.CreateDataPagersForCommand(container, fieldIndex);
}
else
{
this.CreateDataPagersForQueryString(container, fieldIndex);
}
}
The CreateDataPagersForCommand
method creates the controls used to give the functionality to our GooglePagerField
.
private void CreateDataPagersForCommand(DataPagerFieldItem container, int fieldIndex)
{
this.CreateGoToTexBox(container);
this.CreatePageSizeControl(container);
this.CreateLabelRecordControl(container);
if (this._showPreviousPage)
{
container.Controls.Add(this.CreateControl("Prev", this.PreviousPageText,
fieldIndex, this.PreviousPageImageUrl, this._showPreviousPage));
this.AddNonBreakingSpace(container);
}
if (this._showNextPage)
{
container.Controls.Add(this.CreateControl("Next", this.NextPageText,
fieldIndex, this.NextPageImageUrl, this._showNextPage));
this.AddNonBreakingSpace(container);
}
}
HandleEvent method
Handles the events raised by the objects created in the CreateDataPagers
method. This table shows you the commands handled by the HandleEvent
method.
UpdatePageSize | This command occurs when the user selects an item in the 'Show rows' dropdown list. |
GoToItem | This command occurs when the user specify a value in the 'Go to' textbox and presses Enter. |
Prev | This command occurs when the user selects the previous page button. |
Next | This command occurs when the user selects the next page button. |
public override void HandleEvent(CommandEventArgs e)
{
if (string.Equals(e.CommandName, "UpdatePageSize"))
{
base.DataPager.PageSize = Int32.Parse(e.CommandArgument.ToString());
base.DataPager.SetPageProperties(this._startRowIndex,
base.DataPager.PageSize, true);
return;
}
if (string.Equals(e.CommandName, "GoToItem"))
{
int newStartRowIndex = Int32.Parse(e.CommandArgument.ToString());
base.DataPager.SetPageProperties(newStartRowIndex,
base.DataPager.PageSize, true);
return;
}
if (string.IsNullOrEmpty(base.DataPager.QueryStringField))
{
if (string.Equals(e.CommandName, "Prev"))
{
int startRowIndex = this._startRowIndex - base.DataPager.PageSize;
if (startRowIndex < 0)
{
startRowIndex = 0;
}
base.DataPager.SetPageProperties(startRowIndex,
base.DataPager.PageSize, true);
}
else if (string.Equals(e.CommandName, "Next"))
{
int nextStartRowIndex = this._startRowIndex + base.DataPager.PageSize;
if (nextStartRowIndex > this._totalRowCount)
nextStartRowIndex = this._totalRowCount - base.DataPager.PageSize;
if (nextStartRowIndex < 0)
nextStartRowIndex = 0;
base.DataPager.SetPageProperties(nextStartRowIndex,
base.DataPager.PageSize, true);
}
}
}
ButtonDropDownList web control
The ButtonDropDownList
is a custom dropdownlist web control created to allow the user to select the page size. The ButtonDropDownList
web control implements the IPostBackEventHandler
. The IPostBackEventHandler
allows the ButtonDropDownList
web control to raise a Command
event which can be handled by the GooglePagerField
class.
public class ButtonDropDownList : DropDownList, IPostBackEventHandler
{
}
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.
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
this.CommandArgument = "0";
if (base.SelectedItem != null)
this.CommandArgument = this.SelectedItem.Value;
this.RaisePostBackEvent(eventArgument);
}
protected virtual void RaisePostBackEvent(string eventArgument)
{
if (this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}
this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
}
protected virtual void OnCommand(CommandEventArgs e)
{
CommandEventHandler handler = (CommandEventHandler)base.Events[EventCommand];
if (handler != null)
{
handler(this, e);
}
base.RaiseBubbleEvent(this, e);
}
ButtonTextBox web control
The ButtonTextBox
is a custom textbox web control created to allow the user to display the data records beginning at the specified record. The ButtonTextBox
web control implements the IPostBackEventHandler
. The IPostBackEventHandler
allows the ButtonTextBox
web control to raise a Command
event which can be handled by the GooglePagerField
class.
public class ButtonTextBox : TextBox, IPostBackEventHandler
{
}
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.
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
this.CommandArgument = base.Text;
this.RaisePostBackEvent(eventArgument);
}
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.
<asp:ListView ID="ListView1" runat="server"
DataSourceID="AccessDataSource1" ItemPlaceholderID="itemPlaceHolder">
<LayoutTemplate>
<table class="tableInfo">
<tr>
<th>ID</th>
<th>First name</th>
<th>Last name</th>
</tr>
<asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
<tr>
<td colspan="3">
<asp:DataPager ID="DataPager1" runat="server"
PagedControlID="ListView1" PageSize="5" >
<Fields>
<SqlNetFrameworkWebControls:GooglePagerField
NextPageImageUrl="~/Images/button_arrow_right.gif"
PreviousPageImageUrl="~/Images/button_arrow_left.gif" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("PlayerId") %></td>
<td><%# Eval("FirstName") %></td>
<td><%# Eval("LastName") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
Conclusion
The DataPager
web control separates the paging functionality from data-bound web controls. It allows you to have the freedom to customize the paging appearance and functionality to your own needs.
Version history
- Version 1.0. Original version (March 25, 2008).
- Version 1.1. Minor "
GoToItem
" fix (April 8, 2008). Thanks to Joop for the help.