github というサイトの Grid というページに紹介されている JavaScript(jQuery ではない)と CSS を利用して、GridView のヘッダと列を固定する例の紹介です。
先の記事「GridView のヘッダ、列を固定」で、CSS の Internet Explorer (IE) 独自実装である expression 関数を使ってテーブルのヘッダと列を固定する例を書きました。
しかしながら、expression 関数のサポートは終了していて IE でも互換モードでないと動きませんし、IE の独自実装なので、当然、Firefox など他のブラウザでは動きませんので、あまり使い道はありません。
2017/8/16 注記追加
Windows 10 IE11 では Quirks モード(IE5 相当)にしても expression 関数が働かないようです。いつそうなったのかは不明ですが、expression 関数を使ってテーブルのヘッダ・列を固定する方法は使用禁止にした方がよさそうです。
代わりに、上に紹介した Grid のページから入手できる Grid.js と Grid.css を利用して、GridView のヘッダと列を固定するサンプルを作ってみました。これなら IE7+, Firefox, Chrome, Safari, Opera コンパチなので一般的に使えると思います。
上の画像を表示したサンプルコードを以下に書いておきます。注意点は以下およびコード内のコメントに書いておきましたので読んでください。
-
Grid.js は、table の DOM、json 文字列、xml 文字列のいずれかをソースとして、ヘッダや列を固定可能なテーブルを生成します。GridView の場合は、GridView が生成した table の DOM をソースとして使うことになります。
-
GridView が生成した table の DOM は、Grid.js が生成した別テーブルに置き換えられます。つまり、上の画像に表示されているテーブルは GridView ではなく、Grid.js が生成した別物です。
-
Grid.js が生成した別テーブルを操作してデータベースの更新を行うのは無理っぽいです。別テーブルは表示するだけにして、更新は別に DetailsView か FormView を表示して行うのがよさそうです。
実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
// データソース用の DataTable を作成
protected DataTable CreateDataTable()
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Type", typeof(string)));
dt.Columns.Add(new DataColumn("Price", typeof(Int32)));
dt.Columns.Add(new DataColumn("Qty", typeof(Int32)));
dt.Columns.Add(new DataColumn("Amount", typeof(Int32)));
dt.Columns.Add(new DataColumn("CategoryID", typeof(Int32)));
dt.Columns.Add(new DataColumn("Note", typeof(string)));
dt.Columns.Add(new DataColumn("Discontinued", typeof(bool)));
dt.Columns.Add(new DataColumn("DateTime", typeof(DateTime)));
for (int i = 0; i < 50; i++)
{
dr = dt.NewRow();
dr["ID"] = i;
dr["Name"] = "Product Name_" + i.ToString();
dr["Type"] = "Product Type " + (100 - i).ToString();
dr["Price"] = 123000 * (i + 1);
dr["Qty"] = (i + 1) * 20;
dr["Amount"] = 123000 * (i + 1) * (i + 1);
dr["CategoryID"] = 100 - i;
dr["Note"] = "Note_" + i.ToString();
dr["Discontinued"] = (i%2 == 0)? true : false;
dr["DateTime"] = DateTime.Now.AddDays(i);
dt.Rows.Add(dr);
}
return dt;
}
// GridView に上記メソッドで作った DataTable をバインド
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSource = CreateDataTable();
GridView1.DataBind();
}
}
// ソースが DOM の場合、thead, tbody が必要。
// GridView はデフォルトでは thead, tbody は生成
// されないので、以下のコードを使って追加する。
protected void GridView1_RowCreated(
object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.TableSection =
System.Web.UI.WebControls.TableRowSection.TableHeader;
}
else if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.TableSection =
System.Web.UI.WebControls.TableRowSection.TableBody;
}
// フッターがある場合(GridView.ShowFooter が true の場合)は
// 以下のコードのコメントアウトを解除。
//else if (e.Row.RowType == DataControlRowType.Footer)
//{
// e.Row.TableSection =
// System.Web.UI.WebControls.TableRowSection.TableFooter;
//}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="/Scripts/Grid.js" type="text/javascript"></script>
<link href="/css/Grid.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
//<![CDATA[
window.onload = function () {
// GridView は div 要素で囲った table を生成するの
// で、その div 要素を利用する。div 要素に id を付
// 与して初期サイズを指定する CSS を設定する。
// div 要素の直下に table がないと、Grid.js による
// 置き換えがうまくいかない(GridView の table が
// 残ってしまう)ので注意。
var tableGridView =
document.getElementById("<%=GridView1.ClientID%>");
var parentElement = tableGridView.parentNode;
parentElement.setAttribute("id", "myGrid");
parentElement.setAttribute("class", "style1");
// ソートするために各列のデータ型を指定。デフォルト
// は string なので、数字などの列がある場合は指定し
// ないとソート結果が期待通りにならない。
var gridColSortTypes =
["number", "string", "string", "number", "number",
"number", "number", "string", "none", "date"];
// GridView (table) の場合、srcType は "dom" に設定。
// 下のコードの myGrid は table を囲う div 要素の id。
// SrcData には table の id(GridView の ClientID)を
// 設定。その他のパラメータ設定は Grid のページ参照。
// Grid.js は、SrcData に指定された table の DOM を
// ソースに使って別テーブルを生成し、元の table と置
// き換える。
new Grid("myGrid", {
srcType: "dom",
srcData: "<%=GridView1.ClientID%>",
allowGridResize: true,
allowColumnResize: true,
allowClientSideSorting: true,
allowSelections: true,
allowMultipleSelections: true,
showSelectionColumn: false,
colSortTypes : gridColSortTypes,
fixedCols: 1
});
};
//]]>
</script>
<style type="text/css">
/* テーブルの初期サイズの指定 */
.style1
{
width: 400px;
height: 360px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1"
runat="server"
OnRowCreated="GridView1_RowCreated"
EnableViewState="False">
</asp:GridView>
</form>
</body>
</html>