.NET TIPS

[ASP.NET]DataGridコントロールの編集用テキストボックスをカスタマイズするには?

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

 DataGridコントロールの編集機能を使用する場合、既定では編集時に表示されるテキストボックスのサイズが固定であまり実用的ではない。「TIPS:[ASP.NET]DataGridコントロールの編集用テキストボックスを大きくするには?」で示したような方法で動的にそれを変更してしまうこともできるが、DataGridコントロールにはテンプレート列を用いて、編集時に使用される入力用のコントロールを明示的に定義する方法が用意されている。

行の編集時の使用される<EditItemTemplate>要素

 「TIPS:[ASP.NET]DataGridコントロールの行に通し番号を付けるには?」の中で解説しているように、テンプレート列では<asp:TemplateColumn>要素内に<ItemTemplate>要素を記述して、独自の表示形式を持った列が定義可能だ。

 次の例は、「商品名」列にデータソースのNameフィールドにあるデータを表示するためにテンプレート列を用いて記述したものである。

  <asp:TemplateColumn ItemStyle-Width="200" HeaderText="商品名">
    <ItemTemplate>
      <%# DataBinder.Eval(Container.DataItem, "Name") %>
    </ItemTemplate>
  </asp:TemplateColumn>

 <ItemTemplate>要素では、データ表示に使用されるテンプレートを定義するものであるが、ここに<EditItemTemplate>要素を追加して、編集時に表示されるテンプレートを記述することができる。次の記述例では、行の編集時にはTextBoxコントロールを表示し、そのText属性によりテキストボックスの初期値としてそこに表示されていたものと同じデータを設定している。また、テキストボックスの幅をセルと同じ大きさにするためにWidth属性で「100%」を指定している。

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

 DataGridコントロールは、グリッドを描画するときに行が編集対象となっていた場合(DataGridオブジェクトのEditItemIndexプロパティでその行が指定されていた場合)、<EditItemTemplate>要素の内容で行を描画する。編集対象となっていない行については<ItemTemplate>要素の内容を使用する。

 もちろん、<EditItemTemplate>要素では必ずテキストボックスを表示しなければならないというきまりがあるわけではない。テンプレート列においては、編集中の行では<EditItemTemplate>要素の内容が、それ以外の行では<ItemTemplate>要素の内容が表示されるというだけの仕組みである。

テンプレート列を使用して編集するサンプル・プログラム

 次に示すサンプル・プログラムは、「TIPS:[ASP.NET]DataGridコントロールで編集を可能にするには?」で示したプログラムで定義している次のような連結列を、上記の<EditItemTemplate>要素を追加したテンプレート列で置き換えたものだ。

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

 太字で示しているコードが、元のプログラムから書き換えた部分である。

<%@ 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.FindControl("NameBox");
      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:TemplateColumn
            ItemStyle-Width="200"
            HeaderText="商品名">
          <ItemTemplate>
            <%# DataBinder.Eval(Container.DataItem, "Name") %>
          </ItemTemplate>
          <EditItemTemplate>
            <asp:TextBox id="NameBox"
                Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>'
                Width="100%"
                runat="server"/>
          </EditItemTemplate>
        </asp:TemplateColumn>


        <asp:BoundColumn
          ItemStyle-Width="100"
          DataField="Quantity" HeaderText="数量" />

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

    </asp:DataGrid>
  </form>
</body>
</html>
テンプレート列を使用して編集するC#のサンプル・プログラム(edititem.aspx)

 このプログラムの実行結果は次のようになる。

サンプル・プログラム(edititem.aspx)の実行結果
商品名を編集するのに使用されているテキストボックスの幅が広くなっている。

 いま示したサンプル・プログラムでは、連結列をテンプレート列に変更した以外に、元のプログラムから変更した個所がもう1点ある。それは、[更新]ボタンがクリックされたときに、入力された文字列を取り出すためにTextBoxコントロールにアクセスしている部分だ。元のプログラムでは、これは次のようにして行っていた。

TextBox tb1 = (TextBox)e.Item.Cells[1].Controls[0];

 この記述は、セルに含まれるコントロールの並び順に強く依存した書き方である。今回のプログラムでも同様な方法でTextBoxコントロールにアクセスできるが(実際には(TextBox)e.Item.Cells[1].Controls[1]でなければならないが)、この行を次のように記述している。

TextBox tb1 = (TextBox)e.Item.FindControl("NameBox");

 FindControlメソッドはASP.NETのすべてのコントロールが持つメソッドで、コントロールが内包している子コントロールから、指定したid(コントロールに付けられた名前)を持ったコントロールを検索するためのものだ。

 <EditItemTemplate>要素でTextBoxコントロールを独自に定義する場合には、そのときにid属性によりコントロールの名前を指定できるのでFindControlメソッドを利用できる。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コントロールでテンプレート列のセルの値を取得するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

更新履歴
【2003/11/11】 「(TextBox)e.Item.Cells[1].FindControl("NameBox");」となっていた本文中のコードを「(TextBox)e.Item.FindControl("NameBox");」に修正しました。この場合にはセルの指定(Cells[1])は不要でした。
 
「.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 記事ランキング

本日 月間