.NET TIPS

[ASP.NET]DataGridコントロールの同一列内のセルを結合するには?

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

 DataGridコントロールでデータを一覧表示する場合に、連続する行の同一列内に同じデータが並ぶことがある。少々極端ではあるが、次の画面のような場合である。

連続する行の同一列内に同じデータが並んでいるグリッド

 このようなデータの並びの場合、上下に隣り合って同じデータを表示しているセルを1つのセルに結合することにより、グリッドが見やすくなることがある。これにより例えば上記のグリッドは、次に示す画面のように変更することができる。

同じデータのセルを列単位で結合したグリッド

 本稿では、このような同じデータを持ったセルを列ごとに結合する方法について解説する。

列単位でのセルの結合

 セルの結合についてはすでに「TIPS:[ASP.NET]DataGridコントロールのヘッダーを結合するには?」でも解説している。そちらでは1つの行に含まれるセルを横方向に結合していた。ここでは、それを縦方向に行えばよい。

 つまり、ある列において縦方向に並んでいる複数のセルを1つのセルにするには、それらのセルのうち1つだけ残して残りのセルをすべて削除し、残ったセルが占めるべき行数をそのセルのRowSpanプロパティに指定すればよい。この作業を図示すると次のようになる。

複数のセルを1つのセルに置き換える方法
同じデータを表示しているセルのうち1つだけ残して残りのセルをすべて削除し、残ったセルのRowSpanプロパティにそのセルが占める行数を指定する。

 ここではある程度汎用的に利用できるように、この処理を次のような1つのメソッドとしてまとめてみた。

void joinCells(DataGrid dg, int column) {
  int numRow = dg.Items.Count;
  int baseIndex = 0;

  while (baseIndex < numRow) {
    int nextIndex = baseIndex + 1;
    TableCell baseCell = dg.Items[baseIndex].Cells[column];

    while (nextIndex < numRow) {

      TableCell nextCell = dg.Items[nextIndex].Cells[column];

      if (getText(baseCell) == getText(nextCell)) {
        if (baseCell.RowSpan == 0) {
          baseCell.RowSpan = 2;
        } else {
          baseCell.RowSpan++;
        }
        dg.Items[nextIndex].Cells.Remove(nextCell);
        nextIndex++;
      } else {
        break;
      }
    }
    baseIndex = nextIndex;
  }
}
指定された列で複数のセルを1つのセルに置き換えるjoinCellsメソッド

 このメソッドは、第1パラメータに対象となるDataGridオブジェクトを、第2パラメータにグリッド内の列のインデックス番号を指定して呼び出せばよい。

 セルの削除にはTableCellCollectionクラス(System.Web.UI.WebControls名前空間)のRemoveメソッドを利用している。このメソッドでは、削除対象となっているセルをパラメータで指定する。なお、セルのRowSpanプロパティの初期値は1ではなく0であるという点に少し注意が必要だ。

 セルに表示されているテキストを取り出すためのgetTextメソッドは、このメソッドとは別に記述している。今回のサンプル・プログラムでは列の表示にテンプレート列を使用しているために、このメソッドは次のようになっている。

string getText(TableCell tc) {
  DataBoundLiteralControl dblc =
    (DataBoundLiteralControl)tc.Controls[0];
  return dblc.Text;
}
セルに表示されているテキストを取得するためのgetTextメソッド

 この内容については「TIPS:[ASP.NET]DataGridコントロールでテンプレート列のセルの値を取得するには?」で解説している。

 列を連結列により定義している場合にはこのメソッドは単に「return tc.Text」となるが、2種類の列が混ざっている場合には、それぞれを判別してテキストを返すように変更する必要がある。

同一列内のセルを結合するサンプル・プログラム

 先に示した画面のうち、2つ目の画面を表示するプログラムのソース・コードは次のようになっている。

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

<html>
<head>
  <script runat="server">
    void Page_Load(object sender, EventArgs e) {
      MyGrid.DataSource = new object[] {
          new object[] {"■", "▲", "■"},
          new object[] {"■", "●", "■"},
          new object[] {"■", "●", "●"},
          new object[] {"■", "■", "●"},
          new object[] {"●", "■", "●"},
          new object[] {"●", "■", "●"},
      };
      MyGrid.DataBind();

      for (int c = 3; c >= 1; c--) {
        joinCells(MyGrid, c);
      }
    }

    string getText(TableCell tc) {
      DataBoundLiteralControl dblc =
        (DataBoundLiteralControl)tc.Controls[0];
      return dblc.Text;
    }

    void joinCells(DataGrid dg, int column) {
      int numRow = dg.Items.Count;
      int baseIndex = 0;

      while (baseIndex < numRow) {
        int nextIndex = baseIndex + 1;
        TableCell baseCell = dg.Items[baseIndex].Cells[column];

        while (nextIndex < numRow) {

          TableCell nextCell = dg.Items[nextIndex].Cells[column];

          if (getText(baseCell) == getText(nextCell)) {
            if (baseCell.RowSpan == 0) {
              baseCell.RowSpan = 2;
            } else {
              baseCell.RowSpan++;
            }
            dg.Items[nextIndex].Cells.Remove(nextCell);
            nextIndex++;
          } else {
            break;
          }
        }
        baseIndex = nextIndex;
      }
    }
  </script>
</head>

<body>
  <form runat="server">
    <asp:DataGrid id="MyGrid"
        AutoGenerateColumns="false"
        ShowHeader="false"
        BackColor="blue"
        CellSpacing="5"
        Width="100%"
        runat="server" >

      <ItemStyle BackColor="white" HorizontalAlign="center" />

      <Columns>
        <asp:TemplateColumn>
          <ItemTemplate>
            <%# Container.ItemIndex + 1 %>
          </ItemTemplate>
        </asp:TemplateColumn>
        <asp:TemplateColumn>
          <ItemTemplate>
            <%# ((object[])Container.DataItem)[0] %>
          </ItemTemplate>
        </asp:TemplateColumn>
        <asp:TemplateColumn>
          <ItemTemplate>
            <%# ((object[])Container.DataItem)[1] %>
          </ItemTemplate>
        </asp:TemplateColumn>
        <asp:TemplateColumn>
          <ItemTemplate>
            <%# ((object[])Container.DataItem)[2] %>
          </ItemTemplate>
        </asp:TemplateColumn>
      </Columns>

    </asp:DataGrid>
  </form>
</body>
</html>
同一列内のセルを結合するC#のサンプル・プログラム(joincells.aspx)

 セルを結合するjoinCellsメソッドを利用するにあたっては、いくつかの注意点がある。このメソッドは、各列に必ず元の行数分のセルが存在しているという前提で記述している。このため、同じDataGridオブジェクトの複数の列に対してこのメソッドを利用する場合には、最も右側にある列から順に適用しなくてはならない。そうしないと列によっては削除しようとしているセルが見つからずにエラーとなることがある。上記のサンプル・プログラムではデータ連結を行った後、joinCellsメソッドを次のようにして呼び出している。

for (int c = 3; c >= 1; c--) {
  joinCells(MyGrid, c);
}

 同じ理由で、このメソッドによってすでにセルの削除を行っている列に繰り返し適用しようとした場合にも、削除しようとしているセルが見つからずにエラーとなることがある。

 また、グリッド内のいずれかの列はセルを結合しないようにしておかないと、データの並びによってはグリッド全体が小さくなってしまう場合があり得る。このため上記のサンプル・プログラムでは、「TIPS:[ASP.NET]DataGridコントロールの行に通し番号を付けるには?」で示した方法により、グリッドの1列目に行番号を表示している。End of Article

カテゴリ:Webフォーム 処理対象:DataGridコントロール
使用ライブラリ:DataGridコントロール
使用ライブラリ:TableCellCollectionクラス(System.Web.UI.WebControls名前空間)
関連TIPS:[ASP.NET]DataGridコントロールのヘッダーを結合するには?
関連TIPS:[ASP.NET]DataGridコントロールでテンプレート列のセルの値を取得するには?
関連TIPS:[ASP.NET]DataGridコントロールの行に通し番号を付けるには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]DataGridコントロールのヘッダーを結合するには?
DataGridViewコントロールで特定の値のセルを強調表示するには?
[ASP.NET]DataGridコントロールのヘッダーを複数行にするには?
[ASP.NET]DataGridコントロールの各セルにアクセスするには?
DataGridコントロールでクリックされたセルの位置を取得するには?
[ASP.NET]DataGridコントロールでテンプレート列のセルの値を取得するには?
DataGridViewコントロールの連続する同じ値のセルを1つにまとめるには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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 記事ランキング

本日 月間