Pages

Advertisement

Friday, July 13, 2007

Implementing a Fixed GridView Header in ASP.NET

For all their fancy extras, ASP.NET Web controls are basically little engines that spit out HTML. Don't get me wrong; the controls are clever and helpful engines, but it is important to know that the output is HTML.

This article looks at two new ASP.NET Web controls, the GridView and the Panel. The GridView is an updated variant of the basic grid, and the Panel supports a locatable, scrollable region. The ability to scroll helps you pack more information in the available real estate on a Web page. The Panel outputs a <div>, and the GridView (like the DataGrid before it) outputs a <table>.

The text that follows demonstrates how to use styles, a Panel, and the GridView to effectively create a scrollable grid with a fixed header.

Adding a New ASP.NET Panel Control

The ASP.NET Panel control outputs a <div>. This means that you can manipulate the Panel at design time using the Properties window; you can manipulate the Panel at runtime with code behind; and you can manipulate the Panel on the client side as its rendered <div>.

The effect created in the code samples is accomplished using HTML and styles. The technique should work with older ASP applications and earlier ASP.NET applications. (If you are not using Visual Studio 2005, you can try to repeat the effect using plain HTML.)

Defining the Panel Styles

The first step is to add an ASP.NET Panel to a Web page. The Panel is on the Standard tab of the Toolbox. Change the Panel.Class property in the Properties window to fixedHeader. Next, you need to add and define the fixedHeader style.

Note: If you are using the professional version of ASP.NET 2005 or Web Express, some features may not be available. For example, you may not be able to visually set the stylesheet property, but you can still use stylesheets. If you have to link the stylesheet in manually, check Google for information on the <link> tag.

Generally, when you add styles, you add a cascading style sheet (CSS) to your project and reference the stylesheet from your page. There is a StyleSheet property for the Document (Web page), and you can either link the stylesheet with this property or manually add the <link> tag. Additionally, you can build the styles from the Style (builder) property or add the styles in the ASP/HTML using the embedded <style> tag within the <head> tag. The example in this article uses the latter approach to show you the entire listing as one page when you are finished with the sample (see Listing 1).

Listing 1: A Partial List of a Web Page Showing the Embedded <style> Tag

<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" 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 id="Head1" runat="server">
<title>Untitled Page</title>
<style type="text/css">
.fixedHeader
{
overflow: auto;
height: 150px;
}
</style>

</head>
<body>
<form id="form1" runat="server">

The <style> tag is added inside the <head> (header) tag section of the page. Listing 1 defined a style named fixedHeader. Within that style, it indicated that overflow is auto and the height is 150 pixels. Overflow indicates how to manage the content of an object when its contents exceed the height and width of the object. The auto value means that content is clipped and scrollbars are added automatically. A height of 150 pixels is added to ensure that you can easily force the Panel's content to overflow without adding tons of data.

Adding a GridView to the Panel

The next step is to add a GridView to the Panel. For the purposes of this demonstration, the GridView works similarly to the DataGrid. To create the fixed header effect, add data to the grid and define an additional style for the <Table> output by the grid at runtime. Listing 2 contains some sample VB code that adds some arbitrary test data to the GridView. (Any supported code can be used to test the scrolling behavior.)

Listing 2: Sample Code for Testing the GridView

Imports System.Collections.Generic

Partial Class _Default
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load

Dim list As List(Of Data) = New List(Of Data)
Dim I As Integer
For I = 1 To 100
list.Add(New Data("String" + I.ToString(), I))
Next

GridView1.DataSource = list
GridView1.DataBind()

End Sub
End Class

Public Class Data
Private FColumn1 As String
Private FColumn2 As Integer

Public Sub New(ByVal c1 As String, ByVal c2 As String)
FColumn1 = c1
FColumn2 = c2
End Sub

Public Property Column1() As String
Get
Return FColumn1
End Get
Set(ByVal value As String)
FColumn1 = value
End Set
End Property

Public Property Column2() As Integer
Get
Return FColumn2
End Get
Set(ByVal value As Integer)
FColumn2 = value
End Set
End Property
End Class

Listing 3 shows a revised Listing 1, containing the new style for the GridView-cum-table.

Listing 3: Listing 1 Revised to Contain the Additional Style Definition

<%@ 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 id="Head1" runat="server">
<title>Untitled Page</title>
<style type="text/css">
.fixedHeader
{
overflow: auto;
height: 150px;
}

table th
{
border-width: 4px;
border-color: Black;
background-color: Gray;
position: relative;
top: expression(this.parentNode.parentNode.
parentNode.scrollTop-1);
}

</style>
</head>
<body>
<form id="form2" runat="server">

 


The new style applies to any table on this page with a subordinate table header (th). The first three properties defined a border and the background color of the header. The position attribute and the top attribute complete the fixed-header effect. Position relative means that the object is positioned relatively to the normal flow and then offset by the top and left properties. The top attribute is calculated as a result of the expression. The expression refers to the table header's ancestor three levels up, which is the table itself. This code should always work, but you can try getElementByID too.

Listing 4, a partial listing of the rendered HTML page, shows that the table header is nested three levels below the table. The first parent is <tr>, the second parent is <tbody>, and the third parent is the <table> itself.

Listing 4: Partial Listing of the Rendered HTML Page

<div id="Panel1" class="fixedHeader"
style="height:150px;width:200px;overflow-y:scroll;">
<div>
<table cellspacing="0"
rules="all"
border="1"
id="GridView1"
style="border-collapse:collapse;">
<tr>
<th scope="col">Column1</th><th scope="col">Column2</th>
</tr>

When you have added the table th style and run the code, the grid should appear to scroll while the header remains in place (see Figure 1). The technique works pretty well, but the thick table header border is used to hide text that scrolls above the header. Also, you may find it difficult to tuck the information rows—everything but the header—up tight against the header without scrolling data above the header. Some experimentation may be necessary to get the header and nested grid to look natural in the panel.


Figure 1: The GridView Scrolled Halfway Past the Fourth Item

Underneath It All, Just HTML

Good old HTML knowledge is still useful for accomplishing tasks like fixed grid headers.

This article used cascading styles and the new Panel and GridView to fix a header while permitting a grid to scroll. Although it used new controls to demonstrate the technique, it is important to note that ASP.NET Web controls emit HTML underneath, so the technique should work in a vanilla editor with plain HTML tags.

1 comment: