.NET TIPS

[ASP.NET]DataGridコントロールで編集を可能にするには?

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

 DataGridコントロールでは、データの一覧表示だけでなく、グリッド内でのデータの編集もサポートしている。ここではDataGridコントロールで編集機能を使用するための基本的なコーディングについてまとめてみる。

DataGridコントロールでの編集作業

 始めに、DataGridコントロールの持つ編集機能により、実際にどのような編集作業が可能となるかを、今回作成するサンプル・プログラム(editdg.aspx)で簡単に見てみよう。

まず、DataGridコントロールの列の1つとして「編集ボタン列」を定義することにより、[編集]ボタンを含んだ列が表示される。

[編集]ボタンが追加されたDataGridコントロール

[編集]ボタンをクリックすると、テキストが表示されているセルが、そのテキストを含んだテキストボックスに置き換えられ(編集しない列も設定可能)行の内容が編集可能となる。同時に、[編集]ボタンが[更新]ボタンと[中止]ボタンの2つに置き換えられる。

行の内容を編集中のDataGridコントロール
行の各項目はテキストボックスで置き換えられ、[編集]ボタンは[更新]ボタンと[中止]ボタンに変わる。

[中止]ボタンがクリックされた場合には、編集内容は反映されずに行の状態は元に戻る。[更新]ボタンがクリックされた場合には、テキストボックスの内容が一覧表示に反映される。

更新されたDataGridコントロール
[更新]ボタンがクリックされるとデータの変更が確定する。[中止]ボタンがクリックされた場合には、行は編集前の状態に戻る。

 コード上では、[更新]ボタンがクリックされたときのデータソースの更新作業を主に行えばよく、それ以外の処理は非常に簡単なコードで実装することができる。

編集機能の実装手順

 次に、DataGridコントロールに編集機能を実装するための基本的な手順についてまとめる。

手順1:編集ボタン列の定義

 3種類のボタンが表示される編集ボタン列は、1つの<asp:EditCommandColumn>要素を使用して定義する。この要素ではそれぞれのボタン上に表示されるテキストを、EditText、CancelText、UpdateTextの3つの属性で指定する。また、デフォルトではこれらのボタンはリンクボタンとなるが、ButtonType属性で「PushButton」を指定することにより、プッシュボタンが使用できる。

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

 編集ボタン列の定義や、後述のイベント・ハンドラの設定、イベント・ハンドラでの処理などの仕組みは「TIPS:[ASP.NET]DataGridコントロールの列にボタンを表示するには?」で解説しているボタン列と基本的に同じなので、そちらも参考にしていただきたい。

 なお、[編集]ボタンは2つのボタンに置き換わるため、グリッド全体の大きさが変化して見にくくならないようにするには、あらかじめセルの幅を設定しておくなどの工夫が必要となる。

手順2:3つのボタンのイベント・ハンドラの指定

 編集ボタン列に表示されるボタンがクリックされたときには、ボタンに応じてEditCommand、UpdateCommand、CancelCommandの3つのイベントが発生する。これらのイベントが発生したときに呼び出されるメソッドを<asp:DataGrid>タグの属性により、それぞれ次のようにして指定する。

  <asp:DataGrid id="MyGrid"
      OnEditCommand  ="MyGrid_Edit"
      OnUpdateCommand="MyGrid_Update"
      OnCancelCommand="MyGrid_Cancel"
      ……
      runat="server" >
    ……
  </asp:DataGrid>

 あとは、ここで指定した3つのメソッドをそれぞれ実装すればよい。

手順3:[編集]ボタンの処理

 [編集]ボタンがクリックされたときの典型的な処理は次のようになる。なお、2行目で呼び出しているBindMyGridメソッドは、データソースを設定し、DataBindメソッドによりデータ連結を実行する処理をまとめているだけだ。

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

 このメソッドの第2パラメータからは、クリックされたボタンがある行のインデックス番号を取得することができる。そして、DataGridオブジェクトのEditItemIndexプロパティに行のインデックス番号を指定してデータ連結を行えば、その行の編集機能が有効となる。つまり、連結列(<asp:BoundColumn>要素で定義した列)や自動生成された列(<asp:DataGrid>要素でAutoGenerateColumns属性をtrueにした場合)は、TextBoxコントロールに置き換えられ、[編集]ボタンが[更新]ボタンと[中止]ボタンの2つに置き換えられる。

 ただし連結列では、次のようにReadOnly="true"属性を追加することにより、その列の項目は読み取り専用となり、行が編集状態になってもTextBoxコントロールには置き換えられない。

  <asp:BoundColumn
      ReadOnly="true"
      DataField="ID" HeaderText="ID" />

 ちなみに、EditItemIndexプロパティは編集ボタン列に固有のものというわけではない。[編集]ボタンは単なるボタンとしてしか機能しておらず、データ連結時にはEditItemIndexプロパティで指定された行が、上述したような編集可能な状態の行として作成されるだけだ。

手順4:[中止]ボタンの処理

 [中止]ボタンでの処理も次に示すようなほぼ固定的なものになる。

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

 DataGridオブジェクトのEditItemIndexプロパティに-1を指定すると、グリッドはどの行も編集状態となっていない通常の状態に戻る。編集内容はキャンセルされたということで、入力された値については特に気にする必要はない。

手順5:[更新]ボタンの処理

 [更新]ボタンのクリック時には、入力された値を直接TextBoxコントロールから取り出し、データソースやデータソースの基となっているデータベースを自分で更新しなければならない。

 次の例では、入力値を取得するために、編集中の行の2列目と3列目に生成された2つのTextBoxコントロールにアクセスしている。

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];

  // tb1.Textとtb2.Textの値によりデータソースを更新

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

 このメソッドでは、e.Item.Cells[1]が編集中の行に含まれる2列目のセル、そしてe.Item.Cells[1].Controls[0]がそのセルに含まれるTextBoxコントロールを示している。セルに含まれるコントロールへのアクセスについては「TIPS:[ASP.NET]DataGridコントロールのページ移動ボタンをカスタマイズするには?」でも解説しているので参照してほしい。

 最後にEditItemIndexプロパティに-1を代入して編集状態をキャンセルしているが、これが必ずしも必要というわけではない。場合によっては、編集状態を継続したままの方が使い勝手がよいかもしれない。

編集機能を使用したサンプル・プログラム

 先に実行画面を示したサンプル・プログラムのソース・コードは次のようになる。DataGridコントロールの編集機能はデータベースのアクセスと連携させて使用されることが一般的ではあるが、コードをシンプルにし、どこでも試せるようにするために、ここではデータテーブルを動的に作成して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();
    }
  </script>
</head>

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

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

      <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#のサンプル・プログラム(editdg.aspx)

 データテーブルの作成や、その更新処理はすべてProductsクラスにまとめている。このクラス内部での処理についてはここでは割愛させていただくが(これについては「連載:ADO.NET基礎講座」で解説している)、その機能については次に簡単に解説しておく。

 まずページの初回アクセス時には、ProductsクラスのstaticなCreateTableメソッドにより、データテーブルとその初期データを作成し、ページのSessionプロパティに保存している。

Session["userTable"] = Products.CreateTable();

 そして、ページの2回目以降のアクセス時には、次のようにしてデータテーブルを復元している。

Products.Table = (DataTable)Session["userTable"];

 これによりProductsクラス内で保持しているデータテーブルの内容を永続化している。データの更新処理についてはUpdateメソッドにまとめている。

 また、このサンプル・プログラムでは、更新対象となった行からデータソースであるデータテーブル内の対応する行(DataRowオブジェクト)を一意に指定するためにDataGridオブジェクトのDataKeysプロパティを使用している。DataKeysプロパティについては「TIPS:[ASP.NET]DataGridコントロールの行にデータを埋め込むには?」で解説している。

 なお、サンプル・プログラムを実際に試した方は気付いたかもしれないが、今回示した編集機能では、セル内に自動的に表示されるテキストボックスの幅は固定であり、実はそれを変更する手段は標準では用意されていない。これについての対処方法は「TIPS:[ASP.NET]DataGridコントロールの編集用テキストボックスを大きくするには?」や「TIPS:[ASP.NET]DataGridコントロールの編集用テキストボックスをカスタマイズするには?」で解説している。End of Article

カテゴリ:Webフォーム 処理対象:DataGridコントロール
使用ライブラリ:DataGridコントロール
関連TIPS:[ASP.NET]DataGridコントロールの列にボタンを表示するには?
関連TIPS:[ASP.NET]DataGridコントロールのページ移動ボタンをカスタマイズするには?
関連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 記事ランキング

本日 月間