GridView Alphabetical Paging in BottomPagerRow
Sometimes the data will be more helpful if presented in a nice and user friendly manner. I have noticed this in the hierarchical GridView which I had explained earlier in previous articles. Like that, this paging also gives an excellent way to group and present the data on the screen. Whenever there is a need of alphabetical lists such as names, products, cities, you may try the Alphabetical Paging.
Wait! There is no built in support for Alphabetical Paging. So there is a need of this article with complete working source code. I have coded this as far as I can explain easily.Look at the screen shots to have a fair idea about how this suppose to work.
Note:
1) As it is already explained in earlier articles several times, I am not going to explain again how to get the data and how to bind the data from database. So please refer to the Asp.net DataControls section or GridView section for that matter.
Screen Shots
Actual View

No Data View (no data to bind)

Construct the Pager Row
For this example, the buttons for all the alphabets will be placed in the bottom pager. Since totally 26 buttons to be created, to make it simple I created a function to create all the buttons. Just after DataBinding the controls have to be created i.e. the function has to be called. When creating buttons, using the command argument the alphabets are passed and command name is given as PAGINATE for differentiate the command from other commands.
Constraints in Pager Row control creation
1) To wire up the events in asp.net, the controls which are fired the PostBack should be available during the PostBack. Otherwise the event will not be mapped to the respective control. As a result just a PostBack only will happen. Since we are creating the controls at the code behind, the above rule applies.
2) Due to the nature for alphabetical paging, we will display/enable the alphabetical buttons even though there is no data for that particular alphabet. That means when you click on that letter, you will be served with the no records found (technically, the EmptyDataTemplate will be displayed). If the EmptyDataTemplate is displayed, you will no longer see the pager row. As a result you will be in dead end and you can not proceed to click on further letters. To workaround this I have recreated once again the pager row at the EmptyDataTemplate. Finally a reusable function is written for catering both the cases EmptyDataTemplate and pager template at footer.
Paging with the support of RowCommand
The pagination is provided to the GridView with the help of RowCommand. As we have already seen the link buttons with alphabets are assigned with command name, command argument appropriately. So in the row command event the respective alphabet can be fetched. Based on that letter, the data can be fetched from the database. After binding the data the page row has to be recreated.
As I have already mentioned, while creating the pager row, the current DataSource has to be verified for creating pager row for footer or EmptyDataTemplate.
Source Code
Markup(*.ASPX)
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb"
Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<style type="text/css">
.Pager
{
font-family:Georgia;
font-style:italic;
color:Gray;
font-weight:bold;
text-decoration:none;
padding:5px 5px 5px 5px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server"
AllowPaging="true" BorderWidth="2px" AutoGenerateColumns="true" >
<EmptyDataTemplate>
No records found
<asp:Panel runat="server" ID="PagerPanel">
</asp:Panel>
</EmptyDataTemplate>
<PagerSettings Visible="true" />
<PagerTemplate>
<asp:Panel runat="server" ID="PagerPanel">
</asp:Panel>
</PagerTemplate>
</asp:GridView>
</div>
</form>
</body>
</html>
Code Behind(*.ASPX.vb)
Imports System.Data
Imports System.Data.SqlClient
Partial Class _Default
Inherits System.Web.UI.Page
Private ReadOnly Property ConnectionString() As String
Get
Return "Server=.\SQLEXPRESS;Database=NorthWind;" & _
"Trusted_Connection=True"
End Get
End Property
Private ReadOnly Property Connection() As SqlConnection
Get
Dim ConnectionToFetch As New SqlConnection(ConnectionString)
ConnectionToFetch.Open()
Return ConnectionToFetch
End Get
End Property
Public Function GetData() As DataView
Return GetData(String.Empty)
End Function
Public Function GetData(ByVal Prefix As String) As DataView
Dim SelectQry = "SELECT * FROM Products "
If (Not String.IsNullOrEmpty(Prefix)) Then
SelectQry &= " where ProductName like @Prefix + '%' "
End If
Dim SampleSource As New DataSet
Dim SortableView As DataView
Try
Dim SampleCommand As New SqlCommand()
Dim SampleDataAdapter = New SqlDataAdapter()
SampleCommand.CommandText = SelectQry
SampleCommand.Connection = Connection
If (Not String.IsNullOrEmpty(Prefix)) Then
Dim PrefixParam = New SqlParameter("@Prefix", Prefix)
SampleCommand.Parameters.Add(PrefixParam)
End If
SampleDataAdapter.SelectCommand = SampleCommand
SampleDataAdapter.Fill(SampleSource)
SortableView = SampleSource.Tables(0).DefaultView
Catch ex As Exception
Throw ex
End Try
Return SortableView
End Function
Private Sub LoadGrid()
Dim SortableView = GetData()
GridView1.DataSource = SortableView
GridView1.DataBind()
End Sub
Public Function FindControlRecursively(ByVal ParentControl As Control, _
ByVal ControlTobeSearched As String) As Control
Dim FoundControl As New Control
For Each CurrentControl As Control In ParentControl.Controls
Diagnostics.Debug.WriteLine(CurrentControl.ID)
If (CurrentControl.ID = ControlTobeSearched) Then
FoundControl = CurrentControl
Exit For
End If
If (CurrentControl.HasControls) Then
FoundControl = FindControlRecursively(CurrentControl, ControlTobeSearched)
End If
Next
Return FoundControl
End Function
Private Sub CreatePagerRow()
Dim PagerRow = GridView1.BottomPagerRow
Dim PagerPanel As New Panel
If (PagerRow Is Nothing) Then
'the pager row is not available after the postback from
'nodata templet so get it from No Row Template
PagerPanel = FindControlRecursively(GridView1, "PagerPanel")
Else 'if previous postback is from PagerRow
PagerPanel = PagerRow.FindControl("PagerPanel")
PagerRow.Visible = True
End If
CreatePagerRow(PagerPanel)
End Sub
Private Sub CreateEmptyDataPagerRow()
Dim PagerRow = GridView1.BottomPagerRow
Dim ControlFound = FindControlRecursively(GridView1, "PagerPanel")
Dim PagerPanel = DirectCast(ControlFound, Panel)
CreatePagerRow(PagerPanel)
End Sub
Private Sub CreatePagerRow(ByVal PagerPanel As Panel)
For CharIndex = 65 To 90
Dim PagerLink As New LinkButton
PagerLink.Text = Convert.ToChar(CharIndex).ToString()
PagerLink.CommandName = "PAGINATE"
PagerLink.CssClass = "Pager"
PagerLink.CommandArgument = PagerLink.Text
PagerPanel.Controls.Add(PagerLink)
Next
End Sub
Protected Sub _Default_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If (Not IsPostBack) Then
LoadGrid()
End If
CreatePagerRow()
End Sub
Protected Sub GridView1_RowCommand(ByVal sender As Object, _
ByVal e As GridViewCommandEventArgs) _
Handles GridView1.RowCommand
If (e.CommandName = "PAGINATE") Then
Dim PagedData = GetData(e.CommandArgument)
GridView1.DataSource = PagedData
GridView1.DataBind()
If (PagedData.Count > 0) Then 'if data available
CreatePagerRow()
Else 'in case of no data
CreateEmptyDataPagerRow()
End If
End If
End Sub
End Class