.NET TIPS

[ASP.NET]DataGridコントロールのフッターに合計行を表示するには?

デジタルアドバンテージ
2003/11/14

 DataGridコントロールの列として金額や数量などの数値を表示している場合、グリッドの一番下に作成されるフッター行を利用して、その合計を表示することができる。

 次の画面は今回作成するサンプル・プログラムの実行画面である。これは「TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?」で示したサンプル・プログラムに合計表示の機能を追加したものだ。

合計行を表示するサンプル・プログラム(sumdg.aspx)の実行画面
このグリッドでは編集機能も実装している。[編集]ボタンをクリックし「数量」列の値を変更すれば、それに従って合計値も変化するようになっている。

 ここでポイントとなるのは、フッターおよびフッターへの合計の表示と、各行のセルから合計を求める方法である。

フッターの表示

 デフォルトでは、DataGridコントロールにはフッターは表示されない。フッターを表示させるにはまず、<asp:DataGrid>タグにShowFooter="true"属性を追加する必要がある。そしてフッターを表示した場合には、ヘッダーや通常の行と同様に、<FooterStyle>要素によりその行のスタイルが指定可能だ。

  <asp:DataGrid id="MyGrid"
        ShowFooter="true"
        ……
        runat="server" >
    <HeaderStyle BackColor="#5522BB" ForeColor="white" />
    <ItemStyle   BackColor="#EEEEFF" />
    <FooterStyle BackColor="#330099" ForeColor="white" />
    ……
  </asp:DataGrid>

セルの値から合計値を算出

 次にグリッド内の各行に表示されている数値の合計を求める。ここでは「TIPS:[ASP.NET]DataGridコントロールですべての行にアクセスするには?」で解説しているItemDataBoundイベントを利用する方法により、各行がデータ連結される際に呼び出されるメソッドで行に含まれる数値データを取得し、合計値として足し込んでいく。

 ItemDataBoundイベントのイベント・ハンドラとなるこのメソッドは次のようになる。なお、変数sumは合計値を保持するためのフィールドである。

int sum = 0;

void MyGrid_Bound(object Sender, DataGridItemEventArgs e) {
  switch (e.Item.ItemType) {
    case ListItemType.Item:
    case ListItemType.AlternatingItem:
    case ListItemType.EditItem:
      DataRowView drv = (DataRowView)e.Item.DataItem;
      sum += (int)drv["Quantity"];
      break;
  }
}

 行に含まれる数値は、データ連結によりセル内に埋め込まれた文字列としても取得可能だが、ItemDataBoundイベントを利用する場合には、行に連結されるデータソース内の要素に「e.Item.DataItem」として直接アクセスできる。

 データソースがデータテーブル(DataTableオブジェクト)である場合、このメソッドが呼ばれるときのe.Item.DataItemの値はDataRowViewクラス(System.Data名前空間)のオブジェクトである。DataRowViewオブジェクトは、DataTableオブジェクト内の行を示すDataRowオブジェクトから作成された「ビュー」であるが、行内のデータはカラム名を指定したインデクサにより、DataRowオブジェクトと同様にその値を取り出すことができる。

 上記のメソッドでは、switch文のcaseラベルの1つに「ListItemType.EditItem」を加えている点に注意してほしい。今回のサンプル・プログラムでは行の編集を可能にしている。ある行が編集中である場合(DataGridオブジェクトのEditItemIndexプロパティで行を指定している場合)、その行のItemTypeプロパティはListItemType.EditItemとなっているため、編集中の行がグリッドに存在する場合にも正しい合計値を求めるに、このcaseラベルが必要となる。

フッターに合計値を表示

 フッター内にデータを表示するには、それがリテラル文字列であれば、連結列のFooterText属性や、テンプレート列の<FooterTemplate>要素で記述することができる。しかし今回のような場合には、合計値として表示する内容はすべての行のデータ連結後に決まる(もちろんデータソースの各要素からも合計値を求めることができるが)。幸いにしてフッターについてもItemDataBoundイベントが発生し、しかもそれはほかのすべての行が連結し終わった後に発生する。よってフッターに合計値を表示するには、次のようなcaseラベルとコードを上記のswitch文に追加すればよい。

  case ListItemType.Footer:
    e.Item.Cells[2].Text = "合計:" + sum;
    e.Item.Cells[2].Font.Bold = true;
    break;

 フッターのItemTypeプロパティの値はListItemType.Footerである。ここではフッター内の左から3番目のセルに合計値を文字列としてセットし、目立つようにセルのフォントをボールドにしている。

合計行を表示するサンプル・プログラム

 冒頭で示したサンプル・プログラムのソース・コードは次のようになる。すでに述べたように、このプログラムは「TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?」に合計行表示のためのコードを追加している。太字で示している部分が追加したコードだ。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>

<html>
<head>
  <script runat="server">
    public class Products {
      private static DataTable _dt;

      public static DataTable Table {
        get { return _dt; }
        set { _dt = value; }
      }

      public static DataTable CreateTable() {
        // データテーブルの作成
        _dt = new DataTable();
        _dt.Columns.Add(new DataColumn("ID", typeof(int)));
        _dt.Columns.Add(new DataColumn("Name", typeof(string)));
        _dt.Columns.Add(new DataColumn("Quantity", typeof(int)));

        // idカラムは自動設定
        _dt.Columns["ID"].AutoIncrement = true;
        _dt.Columns["ID"].AutoIncrementSeed = 1000;

        // 初期データの登録
        Insert("リンゴ", 5);
        Insert("みかん", 10);
        Insert("さくらんぼ", 3);
        Insert("バナナ", 20);

        return _dt;
      }

      public static void Insert(string name, int num) {
        DataRow dr = _dt.NewRow();
        dr["Name"] = name;
        dr["Quantity"] = num;
        _dt.Rows.Add(dr);
      }

      public static void Update(int id, string name, int num) {
        DataRow dr = _dt.Select("id = " + id)[0];
        dr["Name"] = name;
        dr["Quantity"] = num;
      }
    }

    void BindMyGrid() {
      MyGrid.DataSource = Products.Table;
      MyGrid.DataBind();
    }

    void Page_Load(object sender, EventArgs e) {
      if (!IsPostBack) {
        Session["userTable"] = Products.CreateTable();
        BindMyGrid();
      } else {
        Products.Table = (DataTable)Session["userTable"];
      }
    }

    void MyGrid_Edit(object sender, DataGridCommandEventArgs e) {
      MyGrid.EditItemIndex = e.Item.ItemIndex;
      BindMyGrid();
    }

    void MyGrid_Cancel(object sender, DataGridCommandEventArgs e) {
      MyGrid.EditItemIndex = -1;
      BindMyGrid();
    }

    void MyGrid_Update(object sender, DataGridCommandEventArgs e) {
      TextBox tb1 = (TextBox)e.Item.Cells[1].Controls[0];
      TextBox tb2 = (TextBox)e.Item.Cells[2].Controls[0];

      int id = (int)MyGrid.DataKeys[e.Item.ItemIndex];

      Products.Update(id, tb1.Text, Int32.Parse(tb2.Text));

      MyGrid.EditItemIndex = -1;
      BindMyGrid();
    }

    int sum = 0;

    void MyGrid_Bound(object Sender, DataGridItemEventArgs e) {
      switch (e.Item.ItemType) {
        case ListItemType.Item:
        case ListItemType.AlternatingItem:
        case ListItemType.EditItem:
          DataRowView drv = (DataRowView)e.Item.DataItem;
          sum += (int)drv["Quantity"];
          break;

        case ListItemType.Footer:
          e.Item.Cells[2].Text = "合計:" + sum;
          e.Item.Cells[2].Font.Bold = true;
          break;
      }
    }

  </script>
</head>

<body>
  <form runat="server">
    <asp:DataGrid id="MyGrid"
        OnEditCommand  ="MyGrid_Edit"
        OnUpdateCommand="MyGrid_Update"
        OnCancelCommand="MyGrid_Cancel"
        DataKeyField="ID"
        OnItemDataBound="MyGrid_Bound"
        ShowFooter="true"
        AutoGenerateColumns="false"
        CellPadding="4"
        runat="server" >

      <HeaderStyle BackColor="#5522BB" ForeColor="white" />
      <ItemStyle   BackColor="#EEEEFF" />
      <AlternatingItemStyle BackColor="#DDDDFF" />
      <FooterStyle BackColor="#330099" ForeColor="white" />

      <Columns>
        <asp:BoundColumn
            ItemStyle-Width="80"
            ReadOnly="true"
            DataField="ID" HeaderText="ID" />
        <asp:BoundColumn
            ItemStyle-Width="200"
            DataField="Name" HeaderText="商品名" />
        <asp:BoundColumn
            ItemStyle-Width="100"
            DataField="Quantity" HeaderText="数量" />

        <asp:EditCommandColumn
            EditText  ="編集"
            CancelText="中止"
            UpdateText="更新"
            ButtonType="PushButton"
            HeaderText="編集用ボタン" />
      </Columns>

    </asp:DataGrid>
  </form>
</body>
</html>
合計行を表示するC#のサンプル・プログラム(sumdg.aspx)

 このサンプル・プログラムは、コードの追加を行っただけで、元のコードにはまったく編集を加えていない。End of Article

カテゴリ:Webフォーム 処理対象:DataGridコントロール
使用ライブラリ:DataGridコントロール
使用ライブラリ:DataRowViewクラス(System.Data名前空間)
関連TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?
関連TIPS:[ASP.NET]DataGridコントロールですべての行にアクセスするには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]DataGridコントロールですべての行にアクセスするには?
[ASP.NET]DataGridコントロールのフッターに入力機能を追加するには?
[ASP.NET]GridViewコントロールのフッタ行に合計値/平均値を表示するには?
[ASP.NET]DataGridコントロールのヘッダーを複数行にするには?
[ASP.NET]DataGridコントロールの編集用テキストボックスを大きくするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間