WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

GridView のヘッダ、列を固定(その 2)

by WebSurfer 4. February 2013 21:26

github というサイトの Grid というページに紹介されている JavaScript(jQuery ではない)と CSS を利用して、GridView のヘッダと列を固定する例の紹介です。

GridView に Grid.js, Grid.css を適用

先の記事「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 コンパチなので一般的に使えると思います。

上の画像を表示したサンプルコードを以下に書いておきます。注意点は以下およびコード内のコメントに書いておきましたので読んでください。

  1. Grid.js は、table の DOM、json 文字列、xml 文字列のいずれかをソースとして、ヘッダや列を固定可能なテーブルを生成します。GridView の場合は、GridView が生成した table の DOM をソースとして使うことになります。
  2. GridView が生成した table の DOM は、Grid.js が生成した別テーブルに置き換えられます。つまり、上の画像に表示されているテーブルは GridView ではなく、Grid.js が生成した別物です。
  3. 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>

Tags: ,

JavaScript

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  April 2020  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar