Adsense_top

2009年5月21日木曜日

C# DataGridView セルの結合 その1

DataGridViewでセルを結合にチャレンジしてみました。
まずは見た目だけのセル結合です。ラベルのように表示するだけであれば、この方法で十分だと思います。
セルの描画部を処理するだけです。


上記図は、以下の4列のDataGridViewTextBoxColumnを追加し以下のコードでデータを挿入しています。
int num = 1;
for (int i = 0; i < 10; i++)
dataGridView1.Rows.Add(num++, num++, num++, num++);

これを基に、1列目(Column1)では2行を結合し1セルとします。次に1行おきに2列目、3列目を結合します。


結果このような感じになります。
以下のように「CellPainting」イベントを処理しています。
コードを見ていただければわかりますが大した事はしていません。シコシコと描画処理をしているだけです。

private void dataGridView1_CellPainting(object sender, 
 DataGridViewCellPaintingEventArgs e) {
  DataGridView dv = (DataGridView)sender;
  // 行・列共にヘッダは処理しない
  if(e.RowIndex < 0 || e.ColumnIndex < 0)
    return;

  Rectangle rect;
  DataGridViewCell cell;
  // 1列目の処理
  if(e.ColumnIndex == 0) {
    rect = e.CellBounds;
    // 奇数行(1,3,5..行目 = RowIndexは0,2,4..)
    if(e.RowIndex % 2 == 0) {
      cell = dataGridView1[e.ColumnIndex, e.RowIndex + 1];
      //一つ下の次のセルの高さを足す
      rect.Height += cell.Size.Height;
    }
      // 偶数行の処理
    else {
      cell = dataGridView1[e.ColumnIndex, e.RowIndex - 1];
      // 一つ上のセルの高さを足し、矩形の座標も一つ上のセルに合わす
      rect.Height += cell.Size.Height;
      rect.Y -= cell.Size.Height;
    }
    // セルボーダーライン分矩形の位置を補正
    rect.X -= 1;
    rect.Y -= 1;
    // 背景、セルボーダーライン、セルの値を描画
    e.Graphics.FillRectangle(
    new SolidBrush(e.CellStyle.BackColor), rect);
    e.Graphics.DrawRectangle(
    new Pen(dv.GridColor), rect);
    TextRenderer.DrawText(e.Graphics,
    cell.FormattedValue.ToString(),
    e.CellStyle.Font, rect, e.CellStyle.ForeColor,
    TextFormatFlags.HorizontalCenter
    | TextFormatFlags.VerticalCenter);
    // イベント ハンドラ内で処理を行ったことを通知
    e.Handled = true;
  }
    // 2列目と3列目の結合処理
  else if(e.ColumnIndex == 1) {
    // 奇数行のみ列結合
    if(e.RowIndex % 2 == 0) {
      rect = e.CellBounds;
      cell = dataGridView1[e.ColumnIndex + 1, e.RowIndex];
      // 一つ右のセルの幅を足す
      rect.Width += cell.Size.Width;
      rect.X -= 1;
      rect.Y -= 1;
      e.Graphics.FillRectangle(
      new SolidBrush(e.CellStyle.BackColor), rect);
      e.Graphics.DrawRectangle(new Pen(dv.GridColor), rect);
      TextRenderer.DrawText(e.Graphics,
      e.FormattedValue.ToString(),
      e.CellStyle.Font, rect, e.CellStyle.ForeColor,
      TextFormatFlags.HorizontalCenter
      | TextFormatFlags.VerticalCenter);
      e.Handled = true;
    } else {
      // 2列目の偶数行は、結合を行わないので、通常の描画処理に任せる
      e.Paint(e.ClipBounds, e.PaintParts);
    }
  } else {
    // 3列目の奇数行は描画処理をせずに、
    // イベントハンドラ内で処理を完了したこと通知
    if(e.RowIndex % 2 == 0 && e.ColumnIndex == 2)
      e.Handled = true;
  }
}

正しくは、値の描画の処で「e.CellStyle.Alignment」を確認すべきですが、ここでは簡単にするためにセンターに描画しています。

他に、セルをReadOnlyにする処理や、結合セルのフォーカスがある場合の描画処理、キー入力でのフォーカスの移動の処理が必要です。

上記、未実装の部分は別の日に考えます。あしからず...

2 件のコメント:

  1. 通りすがらー2013年12月27日 23:34

    セルの結合参考にさせて頂きました。
    描画しないでe.handle=trueにする箇所はちょこちょこ再描画しないと乱れますね。ですが実装できたので良かったです。
    ありがとうございました。

    返信削除
  2. datagridviewのスクロールを偶数間隔にするときれいに描画できました

    返信削除