Wednesday, October 19, 2011

Freeze ASP.Net GridView Columns and Header with CSS When working in large s


When working in large spreadsheet in excel I used tofreeze the columns(including First Column) and rows. This is very useful when you want to compare the values in one column with other column values. And regarding header I always freeze it otherwise it is very hard to find what the values are referring to.
Like spreadsheet the GridView as well displaying the data in the tabular format. But unfortunately there is no support for this freezing functionality. What i dislike is, there is no built in support forGridView scrolling. we need to write our own CSS to control this.
So I started looking for an alternative while I found some and I wanted to derive a custom container control which can hold a GridView inside and you can specify the columns to freeze. But the development is on going. I may not be able to complete.  So I would like to share how this can be achieved with Styles and CSS with the help of ASP.net

Important Note: Document Type will impact freezing

Document type will be playing a major role in this freezing portion as changing this to strict will lead to undesirable effects. So keep it Transactional always

Enable Scrolling before Freezing including First Column

As I said earlier there is no built in support for scrolling. So to enable scrolling we need to do few things.
1) Add a container (in our case it is a div) to the GridView. This is the one which is going to give scrolling to the GridView
2) To enable scrolling in this div. Add a style attribute “overflow”

Freeze GridView Header

To freeze header, add a style “position: relative;” to header row. After this the entire header row will be frozen will not move when scrolling vertically up and down. While scrolling horizontally (e.g. left to right), The column header have to move horizontally 
If you just need only to freeze header, then please refer this article here Fixed Header GridView

To achieve this we need to change the left of the column, while scrolling this will do the trick nicely.
leftexpression(document.getElementById("GridViewContainer").scrollLeft-2);

Freezing Columns

To freeze columns the style “position: relative;” has to be added to the column and its header. This is to specify the columns to stay in its place while scrolling. But when scrolling vertically (e.g. up and down) this column will not traverse vertically as the other columns move.
To achieve this we need to change the top of the column, while scrolling this will do the trick nicely.
topexpression(document.getElementById("GridViewContainer").scrollTop-2);

Screen Shots

 
Before scrollingAfter Scrolling

SourceCode 

Markup (*.Aspx)

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
  
    <style type="text/css">
        /* A scrolable div */
        .GridViewContainer
        {         
            overflow: auto;
        }
        /* to freeze column cells and its respecitve header*/
        .FrozenCell
        {
            background-color:Gray;
            position: relative;
            cursor: default;
            left: expression(document.getElementById("GridViewContainer").scrollLeft-2);
        }
        /* for freezing column header*/
        .FrozenHeader
        {
         background-color:Gray;
            position: relative;
            cursor: default;          
            top: expression(document.getElementById("GridViewContainer").scrollTop-2);
            z-index: 10;
        }
        /*for the locked columns header to stay on top*/
        .FrozenHeader.locked
        {
            z-index: 99;
        }
      
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div id="GridViewContainer" class="GridViewContainer" style="width:400px;height:600px;" >
        <asp:GridView ID="GridView1" CssClass="GridView" runat="server" BorderWidth="0px"  AutoGenerateColumns="false" >
            <HeaderStyle CssClass="FrozenHeader" />
            <Columns>
                <asp:BoundField DataField="CustomerID" HeaderText="Customer"
                    ItemStyle-CssClass="FrozenCell" HeaderStyle-CssClass="FrozenCell" />
                <asp:BoundField DataField="ShipName" HeaderText="ShipName" />
                <asp:BoundField DataField="ShipAddress" HeaderText="ShipAddress" />
                <asp:BoundField DataField="ShipCity" HeaderText="ShipCity" />
                <asp:BoundField DataField="ShipCountry" HeaderText="ShipCountry" />
            </Columns>
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Code Behind (*.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 GetSourceData() As DataTable
        Dim SelectQry = "select top 100 * from Orders "
        Dim SourceSource As New DataSet
        Try
            Dim SourceDataAdapter As New SqlDataAdapter(SelectQry, ConnectionString)
            SourceDataAdapter.Fill(SourceSource)
        Catch ex As Exception
            Throw ex
        End Try
        Return SourceSource.Tables(0)
    End Function
    Protected Sub _Default_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load
        If (Not IsPostBack) Then
            LoadGrid()
        End If
    End Sub
    Private Sub LoadGrid()
        GridView1.DataSource = GetSourceData()
        GridView1.DataBind()
    End Sub
End Class