DataGridViewで複数行のセルを結合したい


ぐりぐり  2009-03-18 07:42:13  No: 141700

VB2008のDataGridViewで表を作成したいと思っています。
表の左側の列に大分類があり、その右側に小分類の情報を表示したいと思っています。
この大分類が同じものが複数続くときには複数分の大分類を各行に表示せず、
Excelでいうセル結合をしてひとかたまりにして表示できればいいのですが、
色々検索しても方法が見つかりませんでした。
(DataGridが上記のようなことができないという記事は見つかったのですが。)
もしDataGridViewで上記のようなことが可能であれば、教えて頂きたいのですが、
宜しくお願いいたします。


魔界の仮面弁士  2009-03-18 19:49:00  No: 141701

こういう感じでよいのかな。

Public Class Form1
  Private tbl As New DataTable()
  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    tbl.Columns.Add("大分類", GetType(Integer))
    tbl.Columns.Add("小分類", GetType(Integer))
    tbl.Rows.Add(100, 1)
    tbl.Rows.Add(100, 2)
    tbl.Rows.Add(100, 3)
    tbl.Rows.Add(200, 10)
    tbl.Rows.Add(200, 15)
    tbl.Rows.Add(300, 100)
    tbl.Rows.Add(400, 1)
    tbl.Rows.Add(400, 2)
    tbl.Rows.Add(400, 3)

    DataGridView1.DataSource = tbl
  End Sub

  Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
    e.Handled = False

    If e.ColumnIndex <> 0 OrElse e.RowIndex < 0 Then
      Return  '[大分類]列でなければ何もしない
    ElseIf DataGridView1.Rows(e.RowIndex).IsNewRow Then
      Return  '新規行の時も何もしない
    End If

    '現在行の大分類値
    Dim C As Object = DataGridView1(0, e.RowIndex).Value

    '上の行の大分類値
    Dim U As Object = Nothing
    If e.RowIndex > 0 Then
      U = DataGridView1(0, e.RowIndex - 1).Value
    End If

    '下の行の大分類値
    Dim B As Object = Nothing
    If e.RowIndex < DataGridView1.Rows.Count - 1 Then
      B = DataGridView1(0, e.RowIndex + 1).Value
    End If

    '現在行=下の行なら、現在行の下枠線を消す
    If Integer.Equals(C, B) Then
      e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None
    End If

    '現在行=上の行なら、現在行のテキストを消す
    If Integer.Equals(C, U) Then
      Dim selected As Boolean = CBool(e.State And DataGridViewElementStates.Selected)
      e.PaintBackground(e.CellBounds, selected)
      e.Handled = True
    End If

  End Sub

  Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
    If e.ColumnIndex = 0 OrElse e.RowIndex > 0 Then
      '大分類の値が変更された場合、上の行の大分類列を再描画して、
      '枠線の表示/非表示が反映されるようにする
      DataGridView1.InvalidateCell(0, e.RowIndex - 1)
    End If
  End Sub
End Class


ぐりぐり  2009-03-19 19:26:35  No: 141702

魔界の仮面弁士様、ありがとうございました。
質問ですが、DataGridView1_CellPaintingイベント処理で、
最初の行でe.Handled = Falseとし、
最後のIf文でe.Handled = Trueとしていますが、
これは何か理由があるのでしょうか?
(そもそもe.Handledがどのような効果があるのか理解できておりません。。。)
教えて頂きたく、宜しくお願いいたします。


魔界の仮面弁士  2009-03-19 20:36:54  No: 141703

> 魔界の仮面弁士様、ありがとうございました。
期待する結果になっていましたか?

> そもそもe.Handledがどのような効果があるのか理解できておりません。。。
ユーザー定義描画を行った場合、Handled を True にします。
既定の描画処理に任せる場合は False です。

それと、最後のイベント部分を下記のように差し替えておいてください。

Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
  If e.ColumnIndex = 0 Then
    '大分類の値が変更された場合、前後の行の大分類列を再描画して、
    '枠線の表示/非表示が反映されるようにする
    If e.RowIndex > 0 Then
      DataGridView1.InvalidateCell(0, e.RowIndex - 1)
    End If
    Dim maxRowIndex As Integer = DataGridView1.Rows.Count - 1
    If e.RowIndex < maxRowIndex Then
      DataGridView1.InvalidateCell(0, e.RowIndex + 1)
    End If
  End If
End Sub


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加