WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

DataGrid, GridView に動的に列を追加

by WebSurfer 17. May 2013 16:41

あまり使い道はないと思いますが、DataGrid と GridView に動的に列を追加する方法を備忘録として書いておきます。 (【2021/9/21 追記】もっと簡単かつスマートにできる方法がありました。詳しくは「DataGrid, GridView に動的に列を追加 (2)」を見てください)

DataGrid に動的に列を追加

DataGrid, GridView ともヘッダ、フッタを含め各行は TableCellCollection で構成されているので、そのコレクションの適切な位置に TableCell を追加することが基本です。

追加したセルの中に文字列や CheckBox などを配置したい場合は、当該セルの ControlCollection に LiteralControl や CheckBox を初期化して追加します。

追加するタイミングは、DataGrid なら ItemCreated イベント、GridView なら RowCreated イベントがよさそうです。

その例を以下のコードに示します。上の画像を表示したものです。実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。

<%@ 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">

  // 表示用のデータソース (DataView) を生成
  ICollection CreateDataSource()
  {
    DataTable dt = new DataTable();
    DataRow dr;
       
    dt.Columns.Add(new DataColumn("Item", typeof(Int32)));
    dt.Columns.Add(new DataColumn("Name", typeof(string)));
    dt.Columns.Add(new DataColumn("Price", typeof(decimal)));

    for (int i = 0; i < 5; i++)
    {
      dr = dt.NewRow();

      dr["Item"] = i;
      dr["Name"] = "Name-" + i.ToString();
      dr["Price"] = 1.23m * (i + 1);

      dt.Rows.Add(dr);
    }

    DataView dv = new DataView(dt);
    return dv;
  }

  // 初回のみデータソースを生成してバインド(ポストバック
  // 時は ViewState から自動的にデータを取得するので不要)
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      ICollection dv = CreateDataSource();
      DataGrid1.DataSource = dv;
      DataGrid1.DataBind();
      GridView1.DataSource = dv;
      GridView1.DataBind();
    }
  }
    
  // GataGrid.ItemCreated イベントで列を動的に追加する。
  // ItemDataBound イベントで行うと以下の問題があるので
  // 注意:
  // (1) ポストバック時にはイベントが発生しないので追加
  //     行を再生できず、結果消えてしまう。
  // (2) 追加コントロールの LoadViewState, LoadPostData 
  //     の呼び出しがうまくいかない。結果、以下の例では 
  //     CheckBox の CheckedChanged イベントの発生が期
  //     待通りにならない。
  protected void DataGrid1_ItemCreated(object sender, 
    DataGridItemEventArgs e)
  {
    if (e.Item.ItemType == ListItemType.Header)
    {
      // ヘッダ行に列(セル)を追加。セルの中にリテ
      // ラルを配置。
      TableCell cell = new TableCell();
      cell.Controls.Add(new LiteralControl("追加列"));
      e.Item.Cells.Add(cell);
    }
    else if (e.Item.ItemType == ListItemType.Item ||
      e.Item.ItemType == ListItemType.AlternatingItem)
    {
      // データ行に列(セル)を追加。セルの中に
      // CheckBox を配置。
      TableCell cell = new TableCell();
      CheckBox cb1 = new CheckBox();
      cb1.AutoPostBack = true;
      cb1.ID = "CheckBoxInItemIndex-" + 
        e.Item.ItemIndex.ToString();
      cb1.CheckedChanged += 
        new EventHandler(cb1_CheckedChanged);
      cell.Controls.Add(cb1);
      e.Item.Cells.Add(cell);
    }
    else if (e.Item.ItemType == ListItemType.Footer)
    {
      // フッタ行に列(セル)を追加。セルの中にリテ
      // ラルを配置。
      TableCell cell = new TableCell();
      cell.Controls.Add(new LiteralControl("追加列"));
      e.Item.Cells.Add(cell);
    }
  }

  protected void cb1_CheckedChanged(object sender, 
    EventArgs e)
  {
    CheckBox cb = (CheckBox)sender;
    Label1.Text = cb.ID + " clicked to " + 
      cb.Checked.ToString();
  }

  // DataGrid の場合と同様な理由で RowDataBound イベ
  // ントではなく RowCreated イベントで動的に列を追
  // 加する。
  protected void GridView1_RowCreated(object sender, 
    GridViewRowEventArgs e)
  {
    if (e.Row.RowType == DataControlRowType.Header)
    {
      // ヘッダ行に列(セル)を追加。セルの中にリテ
      // ラルを配置。
      // GridView のヘッダ行は th 要素が使われるので、
      // TableCell でなく TableHeaderCell を用いる。
      TableHeaderCell hc = new TableHeaderCell();
      hc.Controls.Add(new LiteralControl("追加列"));
      e.Row.Cells.Add(hc);
    }
    else if (e.Row.RowType == DataControlRowType.DataRow)
    {
      // データ行に列(セル)を追加。セルの中に
      // CheckBox を配置。
      TableCell cell = new TableCell();
      CheckBox cb2 = new CheckBox();
      cb2.AutoPostBack = true;
      cb2.ID = "CheckBoxInRowIndex-" + 
        e.Row.RowIndex.ToString();
      cb2.CheckedChanged += 
        new EventHandler(cb2_CheckedChanged);
      cell.Controls.Add(cb2);
      e.Row.Cells.Add(cell);
    }
    else if (e.Row.RowType == DataControlRowType.Footer)
    {
      // フッタ行に列(セル)を追加。セルの中にリテ
      // ラルを配置。
      TableCell cell = new TableCell();
      cell.Controls.Add(new LiteralControl("追加列"));
      e.Row.Cells.Add(cell);
    }
  }

  protected void cb2_CheckedChanged(object sender, 
    EventArgs e)
  {
    CheckBox cb = (CheckBox)sender;
    Label2.Text = cb.ID + " clicked to " + 
      cb.Checked.ToString();
  }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>WebSurfer's Page - 実験室</title>
</head>
<body>
  <form id="form1" runat="server">

    <h2>DataGrid</h2>
    <asp:DataGrid ID="DataGrid1"
      runat="server" 
      ShowFooter="True" 
      OnItemCreated="DataGrid1_ItemCreated">
    </asp:DataGrid>
    <asp:Label ID="Label1" runat="server" />

    <h2>GridView</h2>
    <asp:GridView ID="GridView1" 
      runat="server" 
      ShowFooter="True" 
      OnRowCreated="GridView1_RowCreated">
    </asp:GridView>
    <asp:Label ID="Label2" runat="server" />

  </form>
</body>
</html>

Tags: ,

ASP.NET

About this blog

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

Calendar

<<  December 2021  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar