DataGridViewコントロールの連続する同じ値のセルを1つにまとめるには?[2.0のみ、C#、VB].NET TIPS

» 2007年05月17日 05時00分 公開
[遠藤孝信デジタルアドバンテージ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「.NET TIPS」のインデックス

連載目次

 DataGridViewコントロールでは、同じ内容のセルが連続して並ぶ場合に、それらを1つのセルにまとめることにより表示を見やすくできる。以下の画面は通常の表示(上)と同じセルを1つにまとめた場合の表示(下)の例である。

[通常の表示]

[同じセルをまとめた場合の表示]

連続する同じ内容のセルを1つのセルにまとめたDataGridViewコントロール(下)


 このような表示は、不要なセルの値と境界線を消すことにより実現できる。本稿では、次のような手順によりこれを実装している。

  1. セルの値が1つ上のセルと同じであれば、その値を空文字に置き換える
  2. すべてのセルにおいて下側の境界線を描画しない
  3. セルの値が1つ上のセルと同じであれば、そのセルの上側の境界線を描画しない

 1.のセルの値を書き換える処理は、セルが表示される直前にセルごとに発生するCellFormattingイベントのタイミングで行うことができる。また、2.と3.のセルの境界線の描画設定については、セルの描画時にセルごとに発生するCellPaintingイベントのタイミングで行える。どちらのイベントにおいても、イベント・ハンドラに渡されるパラメータから、現在処理中のセルの位置を知ることができる。

 まず以下に、これらの手順を実装したサンプル・プログラムを示す。上記の画面はそのサンプル・プログラムの実行例である。

連続する同じ内容のセルを1つのセルにまとめるサンプル・プログラム

 このサンプル・プログラムでは、DataGridViewコントロールに表示するデータとして、@ITの新着記事についてのRSS情報(RSS 2.0)を使用している。プログラムでは、このRSS情報から、記事の公開日、公開しているフォーラム、記事タイトルのみをグリッドに表示する。RSS情報の取得とDataGridViewコントロールの初期化は、フォームのLoadイベント・ハンドラで行っている。

// dgvgroupedcell.cs

using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

public class MyForm : Form {

  DataGridView dgv;

  // 指定したセルと1つ上のセルの値を比較
  bool IsTheSameCellValue(int column, int row) {

    DataGridViewCell cell1 = dgv[column, row];
    DataGridViewCell cell2 = dgv[column, row - 1];

    if (cell1.Value == null || cell2.Value == null) {
      return false;
    }

    // ここでは文字列としてセルの値を比較
    if (cell1.Value.ToString() == cell2.Value.ToString()) {
      return true;
    } else {
      return false;
    }
  }

  // DataGridViewのCellFormattingイベント・ハンドラ
  void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {

    // 1行目については何もしない
    if (e.RowIndex == 0)
      return;

    if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex)) {
      e.Value = "";
      e.FormattingApplied = true; // 以降の書式設定は不要
    }
  }

  // DataGridViewのCellPaintingイベント・ハンドラ
  void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {

    // セルの下側の境界線を「境界線なし」に設定
    e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None; (1)

    // 1行目や列ヘッダ、行ヘッダの場合は何もしない
    if (e.RowIndex < 1 || e.ColumnIndex < 0)
      return;

    if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex)) {
      // セルの上側の境界線を「境界線なし」に設定
      e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None; (2)
    } else {
      // セルの上側の境界線を既定の境界線に設定
      e.AdvancedBorderStyle.Top = dgv.AdvancedCellBorderStyle.Top; (3)
    }
  }

  // フォームのLoadイベント・ハンドラ
  void MyForm_Load(object sender, EventArgs e) {

    // @ITのRSS情報をデータセットに読み込む
    DataSet ds = new DataSet();
    ds.ReadXml("http://atmarkit.itmedia.co.jp/rss/rss.xml");

    // 3つの列(公開日、フォーラム、タイトル)のみを表示
    dgv.ColumnCount = 3;
    dgv.Columns[0].DataPropertyName = "pubDate";
    dgv.Columns[0].HeaderText = "公開日";
    dgv.Columns[1].DataPropertyName = "category";
    dgv.Columns[1].HeaderText = "フォーラム";
    dgv.Columns[2].DataPropertyName = "title";
    dgv.Columns[2].HeaderText = "記事タイトル";

    // 列の自動生成を行わない
    dgv.AutoGenerateColumns = false;

    // RSS内の<item>要素部分をデータソースとして使用
    dgv.DataSource = ds.Tables["item"];
  }

  // フォームのコンストラクタ
  public MyForm() {
    dgv = new DataGridView();
    dgv.Dock = DockStyle.Fill;
    dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
    dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);
    this.Controls.Add(dgv);
    this.Size = new Size(480, 240);
    this.Load += new EventHandler(MyForm_Load);
  }
}

class Program {
  [STAThread]
  static void Main() {
    Application.Run(new MyForm());
  }
}

// コンパイル方法:csc dgvgroupedcell.cs

連続する同じ内容のセルを1つのセルにまとめるC#のサンプル・プログラム(dgvgroupedcell.cs)
dgvgroupedcell.csのダウンロード

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。