.NET TIPS

[ASP.NET]DataGridコントロールのフッターに入力機能を追加するには?

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

 「TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?」では、DataGridコントロールに編集機能を付けた。さらにここでは、グリッドのフッターに[追加]ボタンとテキストボックスを配置して新しいデータを追加できるようにしてみる。

 フッターでの入力機能を追加したサンプル・プログラムの実行画面は次のようになる。

フッターに入力機能を追加したサンプル・プログラム(insertdg.aspx)の実行画面

 このプログラムでは、商品名と数量をテキストボックスに入力し[追加]ボタンをクリックすれば、グリッドの最後に行が追加される。もちろん追加した行も編集可能だ。

<FooterTemplate>要素を含んだテンプレート列

 元のプログラムでは、連結列(<asp:BoundColumn>要素)を使用して列を定義していた。データの表示に連結列を使用している場合、行の編集時には自動的にテキストボックスが表示されるが、フッターにコントロールを配置する場合には、テンプレート列の<FooterTemplate>要素を使用する必要がある。これにともない、必然的に連結列で表示していた内容を<ItemTemplate>要素で書き直す必要がある。またこの場合には編集時に表示されるテキストボックスも<EditItemTemplate>要素で定義しなくてはならない。

 3つの要素を記述したテンプレート列は次のような骨組みになる。

  <asp:TemplateColumn ……>
    <ItemTemplate>
      ……
    </ItemTemplate>
    <EditItemTemplate>
      ……
    </EditItemTemplate>
    <FooterTemplate>
      ……
    </FooterTemplate>
  </asp:TemplateColumn>

 <ItemTemplate>要素には行の通常表示に、<EditItemTemplate>要素には編集時に使用される内容を記述する。この2つの要素については「TIPS:[ASP.NET]DataGridコントロールの編集用テキストボックスをカスタマイズするには?」で解説している。

 <FooterTemplate>要素で定義した内容は、グリッドの一番下の行として常に表示されるものだ。フッターの表示については「TIPS:[ASP.NET]DataGridコントロールのフッターに合計行を表示するには?」で解説している。

フッターにボタンを表示

 元のプログラムでは、グリッドの一番左に表示される「ID」列を次のようにして定義していた。

  <asp:BoundColumn
    ItemStyle-Width="80"
    ReadOnly="true"
    DataField="ID" HeaderText="ID" />

 フッターにButtonコントロールが表示されるようにテンプレート列を用いて書き換えたものは次のようになる。

  <asp:TemplateColumn ItemStyle-Width="80" HeaderText="ID">
    <ItemTemplate>
      <%# DataBinder.Eval(Container.DataItem, "ID") %>
    </ItemTemplate>
    <FooterTemplate>
      <asp:Button id="NewButton" CommandName="Insert"
        Text="追加" runat="server"/>
    </FooterTemplate>
  </asp:TemplateColumn>

 この列は編集不可としているため<EditItemTemplate>要素の定義は不要だ。<EditItemTemplate>要素がない場合には、行の編集時にも<ItemTemplate>要素が表示されたままとなる。

フッターにテキストボックスを表示

 同様に、「商品」列の定義は次のようにして行っていた。

  <asp:BoundColumn
    ItemStyle-Width="200"
    DataField="Name" HeaderText="商品名" />

 この列のフッターにテキストボックスを追加するためテンプレート列を用いて書き換えたものは次のようになる。

  <asp:TemplateColumn ItemStyle-Width="200" HeaderText="商品名">
    <ItemTemplate>
      <%# DataBinder.Eval(Container.DataItem, "Name") %>
    </ItemTemplate>
    <EditItemTemplate>
      <asp:TextBox id="NameBox" Width="100%"
        Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>'
        runat="server"/>
    </EditItemTemplate>
    <FooterTemplate>
      <asp:TextBox id="NewName" Width="100%" runat="server"/>
    </FooterTemplate>
  </asp:TemplateColumn>

[追加]ボタンがクリックされたときの処理

 通常、ButtonコントロールではClickイベントやCommandイベントに対応してクリック時の処理を行うが、DataGridコントロール内に配置されたボタンがクリックされたときには、DataGridコントロールでItemCommandイベントが発生する。ここでは次のようなItemCommandイベントのイベント・ハンドラを記述して、行の追加を処理している。ItemCommandイベントを扱った方が、クリックされたボタンが含まれる行をe.Itemとして取得でき便利だ。

void MyGrid_Command(object sender, DataGridCommandEventArgs e) {
  if (e.CommandName == "Insert") {
    TextBox tb1 = (TextBox)e.Item.FindControl("NewName");
    TextBox tb2 = (TextBox)e.Item.FindControl("NewQuant");

    Products.Insert(tb1.Text, Int32.Parse(tb2.Text));

    BindMyGrid();
  }
}

 なお、このメソッドの1行目で記述しているif文は必須だ。なぜなら、実際には編集用の3つのボタンがクリックされたときにもこのItemCommandイベントが発生しているためである。このときのe.CommandNameの値はそれぞれ、「Edit」「Update」「Cancel」などになる。

入力機能を追加したサンプル・プログラム

 冒頭で示したサンプル・プログラムのソース・コードは次のようになっている。本稿で解説していないコード部分については「TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?」を参照していただきたい。

<%@ Page Language="C#" Debug="true" %>
<%@ 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.FindControl("NameBox");
    TextBox tb2 = (TextBox)e.Item.FindControl("QuantBox");

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

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

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

  void MyGrid_Command(object sender, DataGridCommandEventArgs e) {
    if (e.CommandName == "Insert") {
      TextBox tb1 = (TextBox)e.Item.FindControl("NewName");
      TextBox tb2 = (TextBox)e.Item.FindControl("NewQuant");

      Products.Insert(tb1.Text, Int32.Parse(tb2.Text));

      BindMyGrid();
    }
  }
</script>
</head>

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

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

  <Columns>
    <asp:TemplateColumn ItemStyle-Width="80" HeaderText="ID">
      <ItemTemplate>
        <%# DataBinder.Eval(Container.DataItem, "ID") %>
      </ItemTemplate>
      <FooterTemplate>
        <asp:Button id="NewButton" CommandName="Insert"
          Text="追加" runat="server"/>
      </FooterTemplate>
    </asp:TemplateColumn>

    <asp:TemplateColumn ItemStyle-Width="200" HeaderText="商品名">
      <ItemTemplate>
        <%# DataBinder.Eval(Container.DataItem, "Name") %>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:TextBox id="NameBox" Width="100%"
          Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>'
          runat="server"/>
      </EditItemTemplate>
      <FooterTemplate>
        <asp:TextBox id="NewName" Width="100%" runat="server"/>
      </FooterTemplate>
    </asp:TemplateColumn>

    <asp:TemplateColumn ItemStyle-Width="100" HeaderText="数量">
      <ItemTemplate>
        <%# DataBinder.Eval(Container.DataItem, "Quantity") %>
      </ItemTemplate>
      <EditItemTemplate>
        <asp:TextBox id="QuantBox" Width="100%"
          Text='<%# DataBinder.Eval(Container.DataItem, "Quantity") %>'
          runat="server"/>
      </EditItemTemplate>
      <FooterTemplate>
        <asp:TextBox id="NewQuant" Width="100%" runat="server"/>
      </FooterTemplate>
    </asp:TemplateColumn>

    <asp:EditCommandColumn
      EditText  ="編集"
      CancelText="中止"
      UpdateText="更新"
      ButtonType="PushButton"
      HeaderText="編集用ボタン" />
  </Columns>
</asp:DataGrid>
</form>
</body>
</html>
入力機能を追加したC#のサンプル・プログラム(insertdg.aspx)

 なお、[追加]ボタンを[編集]ボタンの列のフッターに入れなかったのは、編集ボタン列(<asp:EditCommandColumn>要素)を利用したかったためだ。この列に[追加]ボタンを追加するためには、編集ボタン列もテンプレート列で独自に定義する必要がある。この場合、ButtonコントロールのCommandName属性に上記で述べた値(Edit、Cancel、Update)を設定しておけば、編集ボタン列と同等なテンプレート列が定義可能だ。End of Article

カテゴリ:Webフォーム 処理対象:DataGridコントロール
使用ライブラリ:DataGridコントロール
使用ライブラリ:<asp:TemplateColumn>要素
関連TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?
関連TIPS:[ASP.NET]DataGridコントロールの編集用テキストボックスをカスタマイズするには?
関連TIPS:[ASP.NET]DataGridコントロールのフッターに合計行を表示するには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]DataGridコントロールの編集用テキストボックスをカスタマイズするには?
[ASP.NET]DataGridコントロールで編集を可能にするには?
[ASP.NET]DataGridコントロールの編集用テキストボックスを大きくするには?
[ASP.NET]DataGridコントロールの列にボタンを表示するには?
[ASP.NET]DataGridコントロールの行に通し番号を付けるには?
[ASP.NET]DataGridコントロールのフッターに合計行を表示するには?
[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 記事ランキング

本日 月間