Introduction
GridView
control of ASP.NET makes our task much simpler as compared to HTML tables. But one problem which I always faced with GridView
control is of scrolling headers. I tried several forums and websites, but didn’t come up with a good solution.
In this article, I am trying to solve the problem of scrolling headers in ASP.NET GridView
control.
This article will fulfill the following requirements:
GridView
will have fixed header. GridView
can be scrolled horizontally. GridView
can be scrolled vertically.
Overview
GridView
doesn’t have the ability to scroll. But if the GridView
contains the larger number of rows or columns (say more than 100 rows and 15 columns), we want it to have scrollbars.
Since, the Div
control has the ability to scroll horizontally and vertically, therefore, to achieve scrolling in GridView
, we have to wrap the GridView
in the Div
control. It is the Div
that actually scrolls, but it looks like the GridView
is scrolling.
Wrapping the GridView
in a Div
(say DataDiv
) and making the DataDiv
overflow property to auto solves the problem of scrolling in GridView
, but one problem is that the header of the GridView
also scrolls up while scrolling it vertically (this is because, the DataDiv
is actually scrolling but not the GridView
).
To get the solution of this problem, put another Div
(say HeaderDiv
) above DataDiv
.
The next step is to create a new HTML table in HeaderDiv
which will contain the new header for the GridView
. This job will be done by a JavaScript function (say CreateGridHeader()
). This JavaScript function also sets the HeaderDiv
style as per the DataDiv
and new HTML table style as per GridView
style and also we will hide the original header of GridView
. This function will be called every time after filling the GridView
with data as well as on the Page Load.
At this point, we will have header (new HTML table) and GridView
as different entities.
Since, header and GridView
both are different entities; therefore, one thing which is still left is how to scroll the header while scrolling the GridView
horizontally. This job will be done by a JavaScript function (say Onscrollfnction ()
) which will be executed at the scroll event of the DataDiv
. This function will scroll the HeaderDiv
along with the DataDiv
while scrolling in the horizontal direction.
Objective
The main objective behind the overall exercise is to create the new table (which contains the new header row) above the GridView
with the similar style attributes of the original header and hides the original header of GridView
.
Using the Code
- The first thing we have to do is to put the
GridView
inside the Div
tag and also define a Header Div
which will contain the new Header
as follows:
<%----%>
<div id="HeaderDiv">
</div>
<%----%>
<div id="DataDiv" style="overflow: auto; border: 1px solid olive;
width: 600px; height: 300px;" onscroll="Onscrollfnction();">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true"
CellPadding="6" CssClass="GridViewStyle">
<HeaderStyle CssClass="GridViewHeaderStyle" />
</asp:GridView>
</div>
Please note the following points in the above code:
GridView1
is the GridView
which contains the data. DataDiv
will make the GridView
scrollable (horizontally as well as vertically). To make it scrollable, we have to set its overflow property to auto. - I put a JavaScript function say
Onscrollfnction ()
on DataDiv
scrolling. This function will be executed every time when the DataDiv
scrolls. The main idea behind this function is to scroll the Header
Div along with the DataDiv
. HeaderDiv
will contain the new header for GridView
. - Except this, other styling is not necessary. I just use all other styling for display purposes.
- In the second step, write a JavaScript function
Onscrollfnction()
, which will be executed when you scroll the DataDiv
horizontally.
function Onscrollfnction()
{
var div = document.getElementById('DataDiv');
var div2= document.getElementById('HeaderDiv');
div2.scrollLeft = div.scrollLeft;
return false;
}
This function will scroll the HeaderDiv
along with the DataDiv
while scrolling in horizontal direction.
- The third step is to write a Javascript function
CreateGridHeader()
. This function will create a new header table for the GridView
in HeaderDiv
and hides the original header. This function also resolves the style issues between HeaderDiv
and DataDiv
. This function will be called every time after filling the GridView
with data as well as on the Page Load.
function CreateGridHeader(DataDiv, GridView1, HeaderDiv)
{
var DataDivObj = document.getElementById(DataDiv);
var DataGridObj = document.getElementById(GridView1);
var HeaderDivObj = document.getElementById(HeaderDiv);
var HeadertableObj = HeaderDivObj.appendChild(document.createElement('table'));
DataDivObj.style.paddingTop = '0px';
var DataDivWidth = DataDivObj.clientWidth;
DataDivObj.style.width = '5000px';
HeaderDivObj.className = DataDivObj.className;
HeaderDivObj.style.cssText = DataDivObj.style.cssText;
HeaderDivObj.style.overflow = 'auto';
HeaderDivObj.style.overflowX = 'hidden';
HeaderDivObj.style.overflowY = 'hidden';
HeaderDivObj.style.height = DataGridObj.rows[0].clientHeight + 'px';
HeaderDivObj.style.borderBottomWidth = '0px';
HeadertableObj.className = DataGridObj.className;
HeadertableObj.style.cssText = DataGridObj.style.cssText;
HeadertableObj.border = '1px';
HeadertableObj.rules = 'all';
HeadertableObj.cellPadding = DataGridObj.cellPadding;
HeadertableObj.cellSpacing = DataGridObj.cellSpacing;
var Row = HeadertableObj.insertRow(0);
Row.className = DataGridObj.rows[0].className;
Row.style.cssText = DataGridObj.rows[0].style.cssText;
Row.style.fontWeight = 'bold';
for(var iCntr =0; iCntr < DataGridObj.rows[0].cells.length; iCntr++)
{
var spanTag = Row.appendChild(document.createElement('td'));
spanTag.innerHTML = DataGridObj.rows[0].cells[iCntr].innerHTML;
var width = 0;
if(spanTag.clientWidth > DataGridObj.rows[1].cells[iCntr].clientWidth)
{
width = spanTag.clientWidth;
}
else
{
width = DataGridObj.rows[1].cells[iCntr].clientWidth;
}
if(iCntr<=DataGridObj.rows[0].cells.length-2)
{
spanTag.style.width = width + 'px';
}
else
{
spanTag.style.width = width + 20 + 'px';
}
DataGridObj.rows[1].cells[iCntr].style.width = width + 'px';
}
var tableWidth = DataGridObj.clientWidth;
DataGridObj.rows[0].style.display = 'none';
HeaderDivObj.style.width = DataDivWidth + 'px';
DataDivObj.style.width = DataDivWidth + 'px';
DataGridObj.style.width = tableWidth + 'px';
HeadertableObj.style.width = tableWidth + 20 + 'px';
return false;
}
This function will take three parameters DataDiv
, GridView
, and HeaderDiv
. This function needs to be called from the server side every time the Grid
is filled with data and also on the Page Load.
- The final step is to fill the
GridView
with Data and call the JavaScript function CreateGridHeader ()
from server side. This JavaScript function is also called on page load.
string conString = "Provider=Microsoft.JET.OLEDB.4.0;
data source=" + Server.MapPath (string.Empty) + @"\Database\Northwind.mdb";
string sqlString = "SELECT * FROM CUSTOMERS";
OleDbConnection conn = new OleDbConnection(conString);
DataSet ds = new DataSet();
OleDbDataAdapter adapter = new OleDbDataAdapter(sqlString, conn);
adapter.Fill(ds);
GridView1.DataSource = ds.Tables[0];
GridView1.DataBind();
ClientScript.RegisterStartupScript(this.GetType(), "CreateGridHeader",
"<script>CreateGridHeader('DataDiv', 'GridView1', 'HeaderDiv');</script>");
- The
CreateGridHeader ()
function needs to be called on Page Load also.
protected void Page_Load(object sender, EventArgs e)
{
if (GridView1.Rows.Count > 0)
{
ClientScript.RegisterStartupScript(this.GetType(),
"CreateGridHeader",
"<script>CreateGridHeader('DataDiv', 'GridView1',
'HeaderDiv');</script>");
}
}
You are now ready with the GridView
with fixed headers.
Points of Interest
This solution is tested well with Internet Explorer, Mozilla Firefox, and Google Chrome.
History