[ASP.NET] GridViewコントロールでヘッダーを固定しボディをスクロールする

GridViewコントロールに多くのデータを表示する場合はページング機能が有効ですが、ここではページング機能を使わずに、ヘッダーを固定してボディをスクロール表示する方法について説明します。

jQuery の tbodyScrollというプラグインを使用します。

まず、画面のデザインコードは以下の通りです。

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">
<script src="Scripts/jquery-1.4.1.min.js"></script>
<script src="Scripts/jquery.tbodyscroll.js"></script>
<script>
$(document).ready(function() {
  $('.demo').tbodyScroll({
    thead_height:   '30px',
    tbody_height:   '100px',
    tfoot_height:   '20px'
  });
});  

</script>
<style type="text/css">
.demo { border-collapse: collapse; }
.demo thead th { background-color: blue; color:white }
.demo tfoot th { background-color: green; }

th ,
td {width: 180px;}
</style>
</head>
<body>
    <form id="form1" runat="server">
 
        <asp:GridView ID="GridView1" runat="server" CssClass="demo" ShowFooter="True" OnRowCreated="GridView1_RowCreated">
            <AlternatingRowStyle BackColor="Gainsboro" />
        <Columns>
            <asp:BoundField DataField="Empno" HeaderText="Empno"/>
            <asp:BoundField DataField="Name" HeaderText="Name"/>
            <asp:BoundField DataField="Hiredate" HeaderText="Hiredate"/>
        </Columns>
        </asp:GridView>
    </form>
</body>
</html>

上記コードからもわかるとおり

が必要です(1.4.1で検証しましたが、おそらく他のバージョンでも動くと思われます)。
ダウンロードして Scriptsフォルダに配置します。
8行目の .demo は 画面に配置したGridViewのCssClass属性の値に合わせます。
9行目は、GridViewのヘッダー高さ、10行目はGridViewのデータ表示部の高さ、11行目はGridViewのフッター高さです。
18行目は、GridViewのヘッダーの背景色を青に、前景色を白に設定しています。

次に、GridViewにデータを表示するコードです。

C#の例

/// <summary>
/// 従業員リストクラス
/// </summary>
private class EmployeeList
{
    private string _empno;
    private string _name;
    private DateTime _hiredate;

    /// <summary>
    /// 従業員番号
    /// </summary>
    public string Empno
    {
        get { return _empno; }
        set { _empno = value; }
    }

    /// <summary>
    /// 指名
    /// </summary>
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    /// <summary>
    /// 入社日
    /// </summary>
    public DateTime Hiredate
    {
        get { return _hiredate; }
        set { _hiredate = value; }
    }
}

/// <summary>
/// ページロード時の処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
    //ポストバック時はデータ再作成しない
    if (IsPostBack)
    {
        return;
    }

    List<EmployeeList> emplist = new List<EmployeeList>();

    // 100件のデータを作成
    for (int i = 0; i < 100; i++)
    {
        EmployeeList emp = new EmployeeList();

        emp.Empno = i.ToString().PadLeft(4, '0');
        emp.Name = "User Name" + i.ToString();
        emp.Hiredate = DateTime.Now.AddYears(-i);

        emplist.Add(emp);
    }

    //自動的に列が作成されないようにする
    this.GridView1.AutoGenerateColumns = false;
    GridView1.UseAccessibleHeader = true;
    this.GridView1.DataSource = emplist;
    this.GridView1.DataBind();
}

/// <summary>
/// 行作成時の処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
    switch (e.Row.RowType)
    {
        case DataControlRowType.Header:
            e.Row.TableSection = TableRowSection.TableHeader;   // theadを出力
            break;
        case DataControlRowType.DataRow:
            e.Row.TableSection = TableRowSection.TableBody;     // tbodyを出力
            break;
        case DataControlRowType.Footer:
            e.Row.TableSection = TableRowSection.TableFooter;   // tfootを出力
            break;
    }
}

ここで重要なのは、77~91行目です。
jqueryのtbodyScrollプラグインは、thead, tbody, tfoot要素に対して作用します。
GridViewコントロールで thead, tbody, tfoot の要素を生成する」で紹介したとおり、GridViewはデフォルトではthead, tbody, tfootを出力しないため、77~91行で要素を作成する処理が必要になります。

上記コードを入力後、実行した結果は以下の図のようになります。

ヘッダー固定のGridView

[ASP.NET] GridViewコントロールで thead, tbody, tfoot の要素を生成する

ASP.NETのGridViewコントロールは、デフォルトでは thead, tbody, tfootの要素を生成しません。

試しに、サンプルプロジェクトを作成して、Default.aspxにGridViewコントロールを配置して、以下のようにコードを記述します。

C#の例

using System.Collections.Generic;

/// <summary>
/// 従業員リストクラス
/// </summary>
private class EmployeeList
{
    private string _empno;
    private string _name;
    private DateTime _hiredate;

    /// <summary>
    /// 従業員番号
    /// </summary>
    public string Empno
    {
        get { return _empno; }
        set { _empno = value; }
    }

    /// <summary>
    /// 指名
    /// </summary>
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    /// <summary>
    /// 入社日
    /// </summary>
    public DateTime Hiredate
    {
        get { return _hiredate; }
        set { _hiredate = value; }
    }
}

/// <summary>
/// ページロード時の処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
    List<EmployeeList> emplist = new List<EmployeeList>();

    // 10件のデータを作成
    for (int i = 0; i < 10; i++)
    {
        EmployeeList emp = new EmployeeList();

        emp.Empno = i.ToString().PadLeft(4, '0');
        emp.Name = "User Name" + i.ToString();
        emp.Hiredate = DateTime.Now.AddYears(-i);

        emplist.Add(emp);
    }

    // GridViewにデータを表示
    GridView1.DataSource = emplist;
    GridView1.DataBind();
}

上記の入力が完了したら[F5]を押して実行します。

実行結果は下図のようになります。

GridView

生成された html の table部分は以下の通りで、thead, tbody, tfoot 要素はありません。

<table cellspacing="0" cellpadding="4" border="0" id="GridView1" style="color:#333333;border-collapse:collapse;">
	<tr style="color:White;background-color:#507CD1;font-weight:bold;">
		<th scope="col">Empno</th><th scope="col">Name</th><th scope="col">Hiredate</th>
	</tr><tr style="background-color:#EFF3FB;">
		<td>0000</td><td>User Name0</td><td>2014/05/03 22:15:55</td>
	</tr><tr style="background-color:White;">
		<td>0001</td><td>User Name1</td><td>2013/05/03 22:15:55</td>
	</tr><tr style="background-color:#EFF3FB;">
		<td>0002</td><td>User Name2</td><td>2012/05/03 22:15:55</td>
	</tr><tr style="background-color:White;">
		<td>0003</td><td>User Name3</td><td>2011/05/03 22:15:55</td>
	</tr><tr style="background-color:#EFF3FB;">
		<td>0004</td><td>User Name4</td><td>2010/05/03 22:15:55</td>
	</tr><tr style="background-color:White;">
		<td>0005</td><td>User Name5</td><td>2009/05/03 22:15:55</td>
	</tr><tr style="background-color:#EFF3FB;">
		<td>0006</td><td>User Name6</td><td>2008/05/03 22:15:55</td>
	</tr><tr style="background-color:White;">
		<td>0007</td><td>User Name7</td><td>2007/05/03 22:15:55</td>
	</tr><tr style="background-color:#EFF3FB;">
		<td>0008</td><td>User Name8</td><td>2006/05/03 22:15:55</td>
	</tr><tr style="background-color:White;">
		<td>0009</td><td>User Name9</td><td>2005/05/03 22:15:55</td>
	</tr>
</table>

ここからが本題です。

GridViewコントロールにはRowCreatedという、行を生成したときに発生するイベントがあります。

このイベントの引数、GridViewRowEventArgs の Row.RowTypeを調べると、現在作成されたのが、ヘッダーなのか、ボディなのか、それともフッターなのかを知ることができます。

このとき、Row.TableSelectionプロパティの設定を行うことで、thead, tbody, tfoot の要素を出力することが可能になります。

/// <summary>
/// 行生成時の処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
    switch (e.Row.RowType)
    {
        case DataControlRowType.Header:
            e.Row.TableSection = TableRowSection.TableHeader;   // theadを出力
            break;
        case DataControlRowType.DataRow:
            e.Row.TableSection = TableRowSection.TableBody;     // tbodyを出力
            break;
        case DataControlRowType.Footer:
            e.Row.TableSection = TableRowSection.TableFooter;   // tfootを出力
            break;
    }
}

上記入力後、実行して出力された html の table部分は以下の通りです。

<table cellspacing="0" cellpadding="4" border="0" id="GridView1" style="color:#333333;border-collapse:collapse;">
	<thead>
		<tr style="color:White;background-color:#507CD1;font-weight:bold;">
			<th scope="col">Empno</th><th scope="col">Name</th><th scope="col">Hiredate</th>
		</tr>
	</thead>
	<tbody>
		<tr style="background-color:#EFF3FB;">
			<td>0000</td><td>User Name0</td><td>2014/05/03 22:57:53</td>
		</tr><tr style="background-color:White;">
			<td>0001</td><td>User Name1</td><td>2013/05/03 22:57:53</td>
		</tr><tr style="background-color:#EFF3FB;">
			<td>0002</td><td>User Name2</td><td>2012/05/03 22:57:53</td>
		</tr><tr style="background-color:White;">
			<td>0003</td><td>User Name3</td><td>2011/05/03 22:57:53</td>
		</tr><tr style="background-color:#EFF3FB;">
			<td>0004</td><td>User Name4</td><td>2010/05/03 22:57:53</td>
		</tr><tr style="background-color:White;">
			<td>0005</td><td>User Name5</td><td>2009/05/03 22:57:53</td>
		</tr><tr style="background-color:#EFF3FB;">
			<td>0006</td><td>User Name6</td><td>2008/05/03 22:57:53</td>
		</tr><tr style="background-color:White;">
			<td>0007</td><td>User Name7</td><td>2007/05/03 22:57:53</td>
		</tr><tr style="background-color:#EFF3FB;">
			<td>0008</td><td>User Name8</td><td>2006/05/03 22:57:53</td>
		</tr><tr style="background-color:White;">
			<td>0009</td><td>User Name9</td><td>2005/05/03 22:57:53</td>
		</tr>
	</tbody>
	<tfoot>

	</tfoot>
</table>

このように、Row.TableSelectionプロパティの設定を行うことで、thead, tbody, tfootの要素を出力することができます。