Extended GridView with Fixed Header and Pager






4.50/5 (21 votes)
Extended GridView with Fixed Header and Pager

Introduction
This article is all about creating a custom scrollable gridview
control with fixed header and pager. This gridview is an updated version of ASP.NET basic gridview
and panel supports a localtable, scrollable region and fixed pager solves the last page flickering issue of basic gridview
control.
Problem
When you are using basic ASP.NET gridview
control in your page with AllowPaging=”True”
with PageSize=”12”
, then it renders output 12 rows per page. If the total number of records is 77, then total gridview
will contain total 7 pages. But the problem comes in the last page, which contains 9 records. As a result when you visit the last page in the gridview then the height of the grid will be lesser than the previous page and the pager row will flicker.

Solution
To overcome this issue, I have decided to create a custom gridview control by inheriting the basic ASP.NET GridView
class. Users having knowledge of creating an inherited (custom) control can easily use/understand this article. If you are new then visit the link Developing Custom ASP.NET Server Controls [http://msdn.microsoft.com/en-us/library/zt27tfhy.aspx].
Before we start writing the control, we need a deep look into the basic gridview
control, why this problem occurs. If you see the rendered HTML of basic gridview
control, then you can understand the problems. The gridview
renders a table [see HTML output] in the browser.

- It renders output in a table
- First row contains the header column
- Following rows display the actual data
- And last row displays the pager
So Why the Problem?
Answer: In each page of GridView
total number of row is 14 but in the last page the number of row is 11, which causes flicker in the last page.
Then, What is the Solution?
Answer: If we can split the gridview
table in three separate tables, the first one is for displaying header, the next to display the data in a scrollable region with fixed height and the last to display the pager, then only we can fix this issue. See below:
- Header table displays the header columns
- Data rows are displayed within a fixed-height region “
DIV
” - Pager table displays outside the main grid in separate table
Now if you want to display the grid in this manner, then you need to create a custom GridView
control which will extend the basic functionality of ASP.NET GridView
control.
Steps to Create Custom GridView Control
- Create a class named “
ExGridView
” in your project - Inherit this class from
System.Web.UI.WebControls.GridView
- Override the default control render method
How the Controls Works
ExGridView
is a custom server control which is derived from ASP.NET System.Web.UI.WebControls.GridView
class, Which allows all the functionality of GridView
.
public class ExGridView : GridView
ExGridView
class contains ToolboxData
attribute which specifies the default tag generated for this control when it is dragged from a toolbox in a tool such as Microsoft Visual Studio.
ToolboxData("<{0}:ExGridView runat="\""server\"> </{0}:ExGridView>")
We create actual grid controls in override render
() method. This method is called whenever the postback is performed or when the page is first loaded.
ExGridView
control contains one custom property:
GridHeight
: The fixed height of the container to display the grid data rows
ExGridView
control contains three portions:
Header
: Containinggridview
header row. It displays in a table in top of the grid with same formatting specified in the page.Data
: Containing data rows of the grid view.Pager
: Containing pager row. It displays in a table outside the main grid with the same formatting specified in the page.
Properties
GridHeight
: Get the height of the fixed region where the data rows will be displayed. It acceptsSystem.Web.UI.WebControls.Unit
value
Header Rendering
To display header row outside the main grid we need to create a table with same CellPadding
, CellSpacing
and Width
attribute values of the main grid.
//render header row
writer.Write("<table border='0' cellspacing='" + this.CellSpacing.ToString() +
"' cellpadding='" + this.CellPadding.ToString() + "' style='width:" + CalculateWidth()
+ "'>");
Header table width is calculated using a private method called CalculateWidth()
:
private String CalculateWidth()
{
string strWidth = "auto";
if (!this.Width.IsEmpty)
{
strWidth = String.Format("{0}{1}", this.Width.Value,
((this.Width.Type == UnitType.Percentage) ? "%" : "px"));
}
return strWidth;
}
Assign the HeaderRow
in a variable:
GridViewRow customHeader = this.HeaderRow;
Render HeaderRow
and set the visible property of the default header row to false
.
GridViewRow customHeader = this.HeaderRow;
if (this.HeaderRow != null)
{
customHeader.ApplyStyle(this.HeaderStyle);
if (AutoGenerateColumns == false)
{
int i = 0;
foreach (DataControlField col in this.Columns)
{
customHeader.Cells[i].ApplyStyle(col.HeaderStyle);
i++;
}
}
customHeader.RenderControl(writer);
this.HeaderRow.Visible = false;//make invisible default header row
}
Finally close the table
tag of header:
writer.Write("</table>");
Data Rendering
After rendering the header row, the next step is the rendering of actual data rows in a fixed height region. A DIV
is used as a container of main grid with fixed height and scrolling support.
//render data rows
writer.Write("<div id='" + ClientID + "_div' style='" +
"padding-bottom:5px;overflow-x:hidden;overflow-y:scroll;" +
"width:" + CalculateWidth() + ";" +
"height:" + CalculateHeight() + ";" + "background-color:#FFFFFF;'>");
The overflow-y:scroll
CSS property will display a scrollbar in the DIV
element in browser. The height and width is calculated using private
methods CalculateHeight
and CalculateWidth
.
Now get the pager row, store it in local variable and make invisible that it doesn't display the PagerRow
with main grid table:
//get the pager row and make invisible
GridViewRow customPager = this.BottomPagerRow;
if (this.BottomPagerRow != null)
{
this.BottomPagerRow.Visible = false;
}
Finally render the main grid and close the DIV
tag.
base.Render(writer);
writer.Write("</div>");
Pager Rendering
To render the Pager, create another table and render the PagerRow
which is stored in local variable.
//render pager row
if (customPager != null && this.PageCount > 0)
{
writer.Write("<table border='0' cellspacing='" + this.CellSpacing.ToString() +
"' cellpadding='" + this.CellPadding.ToString() + "' style='width:" + CalculateWidth()
+ "'>");
customPager.ApplyStyle(this.PagerStyle);
customPager.Visible = true;
customPager.RenderControl(writer);
writer.Write("</table>");
}
Using the Code
You can add ExGridView
in your pages. The code below shows how to add this control.
Register the Control
<%@ Register Namespace="CustomControls" TagPrefix="ctrl" %>
Add the Control
<div>
<ctrl:ExGridView ID="GridView1" runat="server" AllowPaging="True" PageSize="18"
AutoGenerateColumns="false" CellPadding="4" DataKeyNames="ProductID"
DataSourceID="SqlDataSource1" ForeColor="#333333"
GridLines="None" GridHeight="250"
Width="100%"> <RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True"
SortExpression="ProductID" HeaderStyle-Width="10%" ItemStyle-Width="10%" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" HeaderStyle-Width="40%" ItemStyle-Width="40%" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" HeaderStyle-Width="10%" ItemStyle-Width="10%" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
SortExpression="UnitsInStock" HeaderStyle-Width="10%" ItemStyle-Width="10%" />
<asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
SortExpression="CategoryName" HeaderStyle-Width="30%" ItemStyle-Width="30%" />
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</ctrl:ExGridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [ProductID], [ProductName], [UnitPrice], [UnitsInStock],
[CategoryName] FROM [Alphabetical list of products]">
</asp:SqlDataSource>
</div>
Important
HeaderStyle-Width
andItemStyle-Width
values should be provided in theasp:BoundField
Known Issues
- Header row doesn't render properly when you set
AutoGenerateColumns=”true”
of the grid view