ラベル DataGridView の投稿を表示しています。 すべての投稿を表示
ラベル DataGridView の投稿を表示しています。 すべての投稿を表示

2013年11月24日日曜日

【VB.NET】BindingNavigatorでフォームのレコードを操作する

BindingNavigatorでフォームのコントロールに連結されたデータレコードの移動や追加・削除といった操作ができます。

フォームにコントロールとBindingSource、BindingNavigatorを配置します。

BindingSourceを各コントロールとBindingNavigatorに連結します。
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'サンプルデータテーブル
        Dim dt As New DataTable
        dt.Columns.Add("商品CD", Type.GetType("System.String"))
        dt.Columns.Add("商品名", Type.GetType("System.String"))
        dt.Columns.Add("単価", Type.GetType("System.Double"))
 
        For i = 1 To 20
            Dim nr As DataRow = dt.NewRow
            nr("商品CD") = i.ToString("000")
            nr("商品名") = "商品" & i.ToString("000")
            nr("単価") = i * 100
            dt.Rows.Add(nr)
        Next
 
        'BindingSource1のDataSourceを設定
        Me.BindingSource1.DataSource = dt
 
        'BindingSource1をBindingNavigator1と連結
        Me.BindingNavigator1.BindingSource = Me.BindingSource1
 
        'BindingSource1を各TextBoxと連結
        Me.TextBox1.DataBindings.Add(New Binding("Text", Me.BindingSource1, "商品CD"))
        Me.TextBox2.DataBindings.Add(New Binding("Text", Me.BindingSource1, "商品名"))
        Me.TextBox3.DataBindings.Add(New Binding("Text", Me.BindingSource1, "単価"))
 
        'BindingSource1をDataGridView1と連結
        Me.DataGridView1.DataSource = Me.BindingSource1
    End Sub
End Class
実行結果

2013年11月10日日曜日

【VB.NET】DataRowViewでDataGridViewの現在の行のDataRowの取得する。

DataRowViewを使いDataGridViewの現在の行(または任意の行)からソース元のDataTableのDataRowを取得します。
Dim dgr As System.Windows.Forms.DataGridViewRow = Me.DataGridView1.CurrentRow
Dim drv As System.Data.DataRowView = CType(dgr.DataBoundItem, System.Data.DataRowView)
Dim dr As DataRow = CType(drv.Row, System.Data.DataRow)
使用例:フォームにDataGridViewとButtonを配置します。
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        'サンプルデータテーブル
        Dim dt As New DataTable
        dt.Columns.Add("NO", Type.GetType("System.Double"))
        dt.Columns.Add("CATEGORY1", Type.GetType("System.String"))
        dt.Columns.Add("CATEGORY2", Type.GetType("System.String"))
        dt.Columns.Add("CATEGORY3", Type.GetType("System.String"))
        dt.Columns.Add("NAME", Type.GetType("System.String"))
        dt.Columns.Add("VAL1", Type.GetType("System.Double"))
        dt.Columns.Add("VAL2", Type.GetType("System.Double"))
        dt.Columns.Add("VAL3", Type.GetType("System.Double"))
        dt.Columns.Add("VAL4", Type.GetType("System.Double"))
        dt.Columns.Add("VAL5", Type.GetType("System.Double"))
 
        Dim r As New System.Random(1000)
 
        Dim no As Integer = 0
        For j1 = 0 To 100
            For j2 = 0 To 5
                For j3 = 0 To 3
                    Dim nr As DataRow = dt.NewRow
                    nr("NO") = no
                    nr("CATEGORY1") = "分類" & j1.ToString("00")
                    nr("CATEGORY2") = "分類" & j2.ToString("00")
                    nr("CATEGORY3") = "分類" & j3.ToString("00")
                    nr("NAME") = "名前" & j1.ToString("00") & j2.ToString("00") & j3.ToString("00")
                    nr("VAL1") = r.Next(10000)
                    nr("VAL2") = r.Next(10000)
                    nr("VAL3") = r.Next(10000)
                    nr("VAL4") = r.Next(10000)
                    nr("VAL5") = r.Next(10000)
                    dt.Rows.Add(nr)
 
                    no += 1
                Next
            Next
        Next
 
        Me.DataGridView1.DataSource = dt
 
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        Dim dgr As System.Windows.Forms.DataGridViewRow = Me.DataGridView1.CurrentRow
        Dim drv As System.Data.DataRowView = CType(dgr.DataBoundItem, System.Data.DataRowView)
        Dim dr As DataRow = CType(drv.Row, System.Data.DataRow)
 
        Console.WriteLine("---------------------------------------------------------")
        For i = 0 To dr.Table.Columns.Count - 1
            Console.WriteLine(dr.Table.Columns(i).ColumnName.ToString & " = " & dr.Item(i).ToString)
        Next
    End Sub
End Class
実行結果

2013年11月3日日曜日

記事を整理

ひとつのコントロールのコードを2つの記事に記載だと分かりづらいので、今までの記事を整理しました。

また【VB.NET】DataGridViewの列ヘッダーの2行表示のコード131~140行に間違いがありましたので修正しました。

2013年10月20日日曜日

【VB.NET】クラスライブラリー

これまでの記事のCustomHeaderDataGridView、CustomHeaderDataGridViewおよび
DataGridViewCustomDropDownComboBoxですが私はクラスライブラリーに作成しました。


クラスライブラリーのプロジェクト構成は以下の通りです。


各クラスのコードは以下の記事に記載されています。
クラスコードを記載した記事
CustomDropDownComboBox.vb【VB.NET】ComboBoxのリストに複数の列を表示する
DropDownColumn.vb
CustomHeaderDataGridView.vb【VB.NET】DataGridViewの列ヘッダーの複数行表示するカスタムコントロール①
HeaderCell.vb
DataGridViewCustomDropDownComboBoxCell.vb【VB.NET】DataGridViewのComboBoxのリストに複数の列を表示する
上記のプロイジェクトをビルドするとビルドの出力先にdllファイルとxmlファイルができます。
(TestFormですがこれは各コントロールの確認の為に使用したもので実際には不要です)


dllファイルとxmlファイルを任意のフォルダに置いて別のプロジェクトで参照しカスタムコントロールを
使用します。

参照方法

     
  1. プロジェクトの「参照」→「追加」→「参照の追加の参照タブを選択」→「任意のフォルダに置いたdllファイルを選択」
  2. 次にツールボックスにdllにあるカスタムコントロールを表示します。
    「ツール」→「ツールボックスアイテムの選択」→「参照」→「任意のフォルダに置いたdllファイルを選択」で.NET FrameWorkコンポーネントにコントロールが表示されるのでチェックを
    入れて「OK」で完了
後はツールボックスからカスタムコントロールをフォームに配置して使用します。

2013年9月10日火曜日

【VB.NET】DataGridViewのComboBoxのリストに複数の列を表示する

DataGridViewComboBoxのDataGridViewComboBoxColumn、DataGridViewComboBoxCellおよび
DataGridViewComboBoxEditingControlの各クラスを継承しドロップダウンリストに複数列表示する
DataGridViewCustomDropDownComboBoxの作成。

【VB.NET】ComboBoxのリストに複数の列を表示と同様に複数列の表示はDataSourceがDataTableの場合のみに限定します。DataSourceがDataTable以外の時は複数列の表示設定は無視されます。

先ず表示する列を定義するコレクションのためのDropDownColumnクラスを作ります。
(これは【VB.NET】ComboBoxのリストに複数の列を表示するのDropDownColumnクラス同じです
したがって同じプロジェクト内に含める場合は追加の必要はありません)

Imports System.Drawing
Imports System.ComponentModel
 
''' <summary>
''' ドロップダウンリストに表示される列の定義
''' </summary>
''' <remarks></remarks>
Public Class DropDownColumn
 
    ''' <summary>
    ''' 列のプロパティ
    ''' </summary>
    ''' <remarks></remarks>
    Private _member As String
 
    ''' <summary>
    ''' 列のプロパティを設定または取得します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("列のプロパティ")>
    Public Property Member As String
        Get
            Return _member
        End Get
        Set(ByVal value As String)
            _member = value
        End Set
    End Property
 
    ''' <summary>
    ''' 列の幅
    ''' </summary>
    ''' <remarks></remarks>
    Private _width As Integer = Nothing
 
    ''' <summary>
    ''' 列の幅を設定または取得します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Description("列の幅")>
    Public Property Width As Integer
        Get
            Return _width
        End Get
        Set(ByVal value As Integer)
            _width = value
        End Set
    End Property
 
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        'インスタンスの初期化
    End Sub
 
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <param name="paramMember">表示する列名</param>
    ''' <param name="paramWidth">幅</param>
    ''' <remarks>ドロップダウンリストに表示される列の定義</remarks>
    Public Sub New(ByVal paramMember As String, ByVal paramWidth As Integer)
        Member = paramMember
        Width = paramWidth
    End Sub
End Class

次に各継承クラスを追加します。
  1. DataGridViewCustomDropDownComboBoxColumn‥DataGridViewComboBoxColumnを継承しCellTemplateに
    DataGridViewCustomDropDownComboBoxCellクラスのインスタンスを設定します。
  2. DataGridViewCustomDropDownComboBoxCell‥DataGridViewComboBoxCellを継承し
    DataGridViewCustomDropListComboBoxEditingControlをホストします。
  3. DataGridViewCustomDropListComboBoxEditingControl‥DataGridViewComboBoxEditingControlを継承しここでドロップダウンリストのアイテムが
    描画される時に複数列を描画します。
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Drawing
 
''' <summary>
''' 複数列のドロップダウンを表示するComboBoxColumn
''' </summary>
''' <remarks></remarks>
Public Class DataGridViewCustomDropDownComboBoxColumn
    Inherits DataGridViewComboBoxColumn
 
    Private _item As New MyCollection(Me)
 
    ''' <summary>
    ''' ドロップダウンリストの列を設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    <Category("ドロップダウンリストの列のカスタマイズ")> _
    <Description("ドロップダウンリストの列を設定します")>
    Public Property DropDownColumns() As MyCollection
        Get
            Return _item
        End Get
        Set(ByVal value As MyCollection)
            _item = value
        End Set
    End Property
 
    ''' <summary>
    ''' ドロップダウンリストの列コレクションの設定。
    ''' </summary>
    ''' <remarks></remarks>
    Public Class MyCollection
        Inherits System.Collections.ObjectModel.Collection(Of DropDownColumn)
 
        Private _parent As DataGridViewCustomDropDownComboBoxColumn
 
        Friend Sub New(ByVal parent As DataGridViewCustomDropDownComboBoxColumn)
            _parent = parent
        End Sub
 
        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
        End Sub
 
        Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As DropDownColumn)
            MyBase.InsertItem(index, item)
 
        End Sub
 
        Protected Overrides Sub RemoveItem(ByVal index As Integer)
            MyBase.RemoveItem(index)
        End Sub
 
        Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As DropDownColumn)
            MyBase.SetItem(index, item)
        End Sub
    End Class
 
    '新しいプロパティを追加しているため、
    ' Cloneメソッドをオーバーライドする必要がある
    Public Overrides Function Clone() As Object
        Dim col As DataGridViewCustomDropDownComboBoxColumn = _
            DirectCast(MyBase.Clone(), DataGridViewCustomDropDownComboBoxColumn)
        col.DropDownColumns = Me.DropDownColumns
        Return col
    End Function
 
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        Dim cel As New DataGridViewCustomDropDownComboBoxCell
        Me.CellTemplate = cel
    End Sub
 
    ''' <summary>
    ''' 現在選択されている行のメンバーの値を取得します。
    ''' </summary>
    ''' <param name="member"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property selectMemberValue(ByVal member As String)
        Get
            Dim cel As DataGridViewCustomDropDownComboBoxCell = _
                TryCast(Me.CellTemplate, DataGridViewCustomDropDownComboBoxCell)
 
            Return cel.selectMemberValue(member)
        End Get
    End Property
End Class
 
''' <summary>
''' 複数列のドロップダウンを表示するComboBoxCell
''' </summary>
''' <remarks></remarks>
Public Class DataGridViewCustomDropDownComboBoxCell
    Inherits DataGridViewComboBoxCell
 
    ''' <summary>
    ''' EditType
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides ReadOnly Property EditType() As Type
        Get
            Return GetType(DataGridViewCustomDropListComboBoxEditingControl)
        End Get
    End Property
 
    ''' <summary>
    ''' InitializeEditingControl
    ''' </summary>
    ''' <param name="rowIndex"></param>
    ''' <param name="initialFormattedValue"></param>
    ''' <param name="dataGridViewCellStyle"></param>
    ''' <remarks></remarks>
    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, _
                                                  ByVal dataGridViewCellStyle As DataGridViewCellStyle)
        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
 
        'セルを格納している複数列表示のコンボボックス列を取得
        Dim clm As DataGridViewCustomDropDownComboBoxColumn = _
            TryCast(Me.OwningColumn, DataGridViewCustomDropDownComboBoxColumn)
 
        '現在のセルでホストされている複数列表示のコンボボックスコントロール
        Dim ctrl As DataGridViewCustomDropListComboBoxEditingControl = _
            TryCast(DataGridView.EditingControl, DataGridViewCustomDropListComboBoxEditingControl)
 
        ctrl.ownerCell = Me
 
        'ホストされている複数列表示のコンボボックスコントロールの列の設定をクリア
        ctrl.DropDownColumns.Clear()
 
        'ホストされている複数列表示のコンボボックスコントロールの列の設定
        For i = 0 To clm.DropDownColumns.Count - 1
            ctrl.DropDownColumns.Add(New DropDownColumn(clm.DropDownColumns(i).Member, clm.DropDownColumns(i).Width))
        Next
 
    End Sub
 
    ''' <summary>
    ''' 現在選択されている行のメンバーの値を取得します。
    ''' </summary>
    ''' <param name="member"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property selectMemberValue(ByVal member As String)
        Get
            '現在のセルでホストされている複数列表示のコンボボックスコントロール
            Dim ctrl As DataGridViewCustomDropListComboBoxEditingControl = _
                TryCast(DataGridView.EditingControl, DataGridViewCustomDropListComboBoxEditingControl)
 
            Return ctrl.selectMemberValue(member)
        End Get
    End Property
 
End Class
 
''' <summary>
''' DataGridViewCustomDropListComboBoxEditingControl
''' </summary>
''' <remarks></remarks>
Public Class DataGridViewCustomDropListComboBoxEditingControl
    Inherits DataGridViewComboBoxEditingControl
 
    Private _item As New MyCollection(Me)
 
    ''' <summary>
    ''' ドロップダウンリストの列を設定します。
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    <Category("ドロップダウンリストの列のカスタマイズ")> _
    <Description("ドロップダウンリストの列を設定します")>
    Public Property DropDownColumns() As MyCollection
        Get
            Return _item
        End Get
        Set(ByVal value As MyCollection)
            _item = value
        End Set
    End Property
 
    ''' <summary>
    ''' ドロップダウンリストの列コレクションの設定。
    ''' </summary>
    ''' <remarks></remarks>
    Public Class MyCollection
        Inherits System.Collections.ObjectModel.Collection(Of DropDownColumn)
 
        Private _parent As DataGridViewCustomDropListComboBoxEditingControl
 
        Friend Sub New(ByVal parent As DataGridViewCustomDropListComboBoxEditingControl)
            _parent = parent
        End Sub
 
        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
        End Sub
 
        Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As DropDownColumn)
            MyBase.InsertItem(index, item)
        End Sub
 
        Protected Overrides Sub RemoveItem(ByVal index As Integer)
            MyBase.RemoveItem(index)
        End Sub
 
        Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As DropDownColumn)
            MyBase.SetItem(index, item)
        End Sub
    End Class
 
    Property ownerCell As DataGridViewCustomDropDownComboBoxCell = Nothing
 
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        Me.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed
    End Sub
 
    ''' <summary>
    ''' 現在選択されている行のメンバーの値を取得します。
    ''' </summary>
    ''' <param name="member"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property selectMemberValue(ByVal member As String)
        Get
            'データソースがない場合はNothingを返す。
            If MyBase.DataSource Is Nothing Then
                Return Nothing
            End If
 
            'データソースがデータテーブルでない場合はNothingを返す。
            If MyBase.DataSource.GetType IsNot GetType(DataTable) Then
                Return Nothing
            End If
 
            'DataTableを取得
            Dim dt As DataTable = CType(Me.DataSource, DataTable)
 
            'メンバーがデータテーブルの列でない場合はNothingを返す。
            If dt.Columns.IndexOf(member) = -1 Then
                Return Nothing
            End If
 
            'メンバーがデータテーブルの列の場合値を返す。
            Return dt.Rows(Me.SelectedIndex).Item(member)
        End Get
    End Property
 
    ''' <summary>
    ''' ドロップダウンリストItemが描画される時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
        MyBase.OnDrawItem(e)
        '選択されているアイテムのハイライト
        e.DrawBackground()
        e.DrawFocusRectangle()
 
        'データソースがない場合は除外。
        If MyBase.DataSource Is Nothing Then
            Exit Sub
        End If
 
        'データソースがデータテーブルでない場合は除外
        If MyBase.DataSource.GetType IsNot GetType(DataTable) Then
            Exit Sub
        End If
 
        'データテーブルの取得
        Dim dt As DataTable = CType(MyBase.DataSource, DataTable)
 
        'アイテムの描画座標の取得
        Dim x As Integer = e.Bounds.X
        Dim y As Integer = e.Bounds.Y
        Dim width As Integer = e.Bounds.X
        Dim height As Integer = e.Bounds.Height
        Dim top As Integer = e.Bounds.Top
        Dim bottom As Integer = e.Bounds.Bottom
 
        '色の取得
        Dim grayPen As New Pen(Brushes.Gray)
        Dim brsh As New SolidBrush(e.ForeColor)
 
        '文字列の表示形式
        Dim sf As New StringFormat
        sf.Trimming = StringTrimming.EllipsisWord
 
        Try
            For i = 0 To Me.DropDownColumns.Count - 1
 
                '列の幅の取得
                width = Me.DropDownColumns(i).Width
 
                '最後の列の時は幅は右端まで
                If i = Me.DropDownColumns.Count - 1 AndAlso Me.Width > Me.DropDownWidth Then
                    width += Me.DropDownWidth - width
                End If
 
                '列の境界線の描画
                If i < Me.DropDownColumns.Count - 1 Then
                    e.Graphics.DrawLine(grayPen, x + width, top, x + width, bottom)
                End If
 
                '列のメンバーの取得
                Dim columnIndex As String = Me.DropDownColumns(i).Member
 
                '列のメンバーがない場合またはデータテーブルの列でない場合は除外
                If columnIndex Is Nothing OrElse columnIndex = String.Empty _
                    OrElse dt.Columns.IndexOf(columnIndex) = -1 Then
                    x += width
                    Continue For
                End If
 
                '列に表示する値を取得
                Dim text As String = dt.Rows(e.Index)(columnIndex).ToString
                '描画領域
                Dim rectF As New RectangleF(CSng(x), CSng(y), CSng(width), CSng(height))
                '値の描画
                e.Graphics.DrawString(text, e.Font, brsh, rectF, sf)
 
                '次の列の座標
                x += width
 
            Next
        Finally
            'リソースの解放
            grayPen.Dispose()
            brsh.Dispose()
            sf.Dispose()
        End Try
    End Sub
 
End Class
以下は簡単な使用例です。
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        'テーブルの作成
        Dim DtPerson As New DataTable
 
        DtPerson.Columns.Add("ID", Type.GetType("System.String"))
        DtPerson.Columns.Add("NAME", Type.GetType("System.String"))
        DtPerson.Columns.Add("ADDRESS", Type.GetType("System.String"))
 
        For i = 0 To 10
            Dim nr As DataRow = DtPerson.NewRow
            nr("ID") = i.ToString("000")
            nr("NAME") = "氏名" & i.ToString("000")
            nr("ADDRESS") = "新潟県○○市" & i.ToString("000")
            DtPerson.Rows.Add(nr)
 
        Next
 
        'DataGridViewComboBoxColumnを作成()
        Dim comboBoxColumn As New DataGridViewCustomDropDownComboBoxColumn
 
        With comboBoxColumn
            .HeaderText = "ID"
            .DataPropertyName = "ID"
            .DisplayMember = "ID"
            .ValueMember = "ID"
            .DataSource = DtPerson
            .DropDownWidth = 450
            .DropDownColumns.Add(New MyLibrary.DropDownColumn("ID", 100))
            .DropDownColumns.Add(New MyLibrary.DropDownColumn("NAME", 150))
            .DropDownColumns.Add(New MyLibrary.DropDownColumn("ADDRESS", 200))
        End With
 
        Me.DataGridView1.Columns.Add(comboBoxColumn)
    End Sub
End Class
実行結果
以外にあっさりできたので色々不具合でもあるのではと考えてしまいます。

2013年8月8日木曜日

【VB.NET】DataGridViewの列ヘッダーの複数行表示するカスタムコントロール②


前回の記事で作成したCustomDataGridViewの使用例です。

プロジェクトにフォームを追加しツールボックスからCustomDataGridViewをフォームに配置します。

先ずはColumnHeaderHeigthSizeModeプロパティをAutoSize以外に設定します。
次に新たに追加したプロパティを設定します。

HeaderCellプロパティをクリックするとHeaderCellコレクションエディターが開くので
HeaderCellを追加設定します。
OKボタンをクリックするとHeaderCellの設定がフォームデザイナーのCustomDataGridViewに
反映されます。

実行結果

HeaderCellは並び順に上書きされます。


またフォームにCustomDataGridviewを配置しコードからプロパティの設定もできます。



Imports System.Reflection
Imports System.Windows.Forms.ComboBox

Public Class Form1
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        'サンプルデータテーブル
        Dim dt As New DataTable
        dt.Columns.Add("NO", Type.GetType("System.Double"))
        dt.Columns.Add("CATEGORY1", Type.GetType("System.String"))
        dt.Columns.Add("CATEGORY2", Type.GetType("System.String"))
        dt.Columns.Add("CATEGORY3", Type.GetType("System.String"))
        dt.Columns.Add("NAME", Type.GetType("System.String"))
        dt.Columns.Add("VAL1", Type.GetType("System.Double"))
        dt.Columns.Add("VAL2", Type.GetType("System.Double"))
        dt.Columns.Add("VAL3", Type.GetType("System.Double"))
        dt.Columns.Add("VAL4", Type.GetType("System.Double"))
        dt.Columns.Add("VAL5", Type.GetType("System.Double"))

        Dim r As New System.Random(1000)

        Dim no As Integer = 0
        For j1 = 0 To 100
            For j2 = 0 To 5
                For j3 = 0 To 3
                    Dim nr As DataRow = dt.NewRow
                    nr("NO") = no
                    nr("CATEGORY1") = "分類" & j1.ToString("00")
                    nr("CATEGORY2") = "分類" & j2.ToString("00")
                    nr("CATEGORY3") = "分類" & j3.ToString("00")
                    nr("NAME") = "名前" & j1.ToString("00") & j2.ToString("00") & j3.ToString("00")
                    nr("VAL1") = r.Next(10000)
                    nr("VAL2") = r.Next(10000)
                    nr("VAL3") = r.Next(10000)
                    nr("VAL4") = r.Next(10000)
                    nr("VAL5") = r.Next(10000)
                    dt.Rows.Add(nr)

                    no += 1
                Next
            Next
        Next

        
        'CustomHeaderDataGridView1の設定
        Me.CustomHeaderDataGridView1.DataSource = dt

        Me.CustomHeaderDataGridView1.ColumnHeaderBorderStyle = CustomHeaderDataGridView.HeaderCellBorderStyle.DoubleLine
        Me.CustomHeaderDataGridView1.ColumnHeaderRowCount = 2
        Me.CustomHeaderDataGridView1.ColumnHeaderRowHeight = 17

        'ヘッダーセル定義
        Dim cells As New HeaderCell
        cells.Column = 0
        cells.Row = 0
        cells.ColumnSpan = 1
        cells.RowSpan = 2
        cells.SortVisible = True
        cells.Text = "NO"
        cells.TextAlign = DataGridViewContentAlignment.MiddleCenter
        Me.CustomHeaderDataGridView1.HeaderCells.Add(cells)

        cells = New HeaderCell
        cells.Column = 1
        cells.Row = 0
        cells.ColumnSpan = 3
        cells.RowSpan = 1
        cells.SortVisible = True
        cells.Text = "CATEGORY"
        cells.TextAlign = DataGridViewContentAlignment.MiddleCenter
        Me.CustomHeaderDataGridView1.HeaderCells.Add(cells)

        cells = New HeaderCell
        cells.Column = 4
        cells.Row = 0
        cells.ColumnSpan = 1
        cells.RowSpan = 2
        cells.SortVisible = True
        cells.Text = "NAME"
        cells.TextAlign = DataGridViewContentAlignment.MiddleCenter
        Me.CustomHeaderDataGridView1.HeaderCells.Add(cells)

        cells = New HeaderCell
        cells.Column = 5
        cells.Row = 0
        cells.ColumnSpan = 5
        cells.RowSpan = 1
        cells.SortVisible = True
        cells.Text = "VAL"
        cells.TextAlign = DataGridViewContentAlignment.MiddleCenter
        Me.CustomHeaderDataGridView1.HeaderCells.Add(cells)

        'ヘッダーサイズモード
        Me.CustomHeaderDataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
    End Sub
End Class
実行結果
(注意点) 
ColumnHeadersHeightSizeModeは手動でAutoSize以外に変更する必要があります。
四角形と文字を描画しているだけなので結合されたセル上でマウスクリックされた場合はその直下の列がソートされます。

2013年8月4日日曜日

【VB.NET ・C#】DataGridViewの列ヘッダーの複数行表示するカスタムコントロール①

DataGridViewを継承して列ヘッダーの複数行表示をするカスタムコントロールをつくります。

先ずは列ヘッダーのセルの結合のための定義をコレクションエディターで表示するためにHeaderCellクラスをプロジェクトに追加します。ヘッダーセル定義は以下の項目にします。
項目意味
Column
Row
ColumnSpan結合する列数
RowSpan結合する行数
BackgroundColorセルの背景色
ForeColorセルの文字色
SortVisible結合したセル内にソートされた列がある場合のソート方向の表示の有無
Textセルに関連付けられたテキスト
TextAlign結合されたセル内のテキストの位置

VB.NET
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing

'Public Class HeaderCellColection
'    Inherits System.Collections.Generic.List(Of HeaderCell)
'End Class

''' <summary>
''' ヘッダーセル定義
''' </summary>
''' <remarks></remarks>
Public Class HeaderCell

    Private _row As Integer
    ''' <summary>
    ''' 行
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル位置")> _
    <Description("行")>
    Public Property Row As Integer
        Get
            Return _row
        End Get
        Set(ByVal value As Integer)
            _row = value
        End Set
    End Property

    Private _column As Integer
    ''' <summary>
    ''' 列
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル位置")> _
    <Description("列")>
    Public Property Column As Integer
        Get
            Return _column
        End Get
        Set(ByVal value As Integer)
            _column = value
        End Set
    End Property

    Private _rowSpan As Integer = 1
    ''' <summary>
    ''' 結合する行数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル結合")> _
    <Description("行数")>
    Public Property RowSpan As Integer
        Get
            Return _rowSpan
        End Get
        Set(ByVal value As Integer)
            _rowSpan = value
        End Set
    End Property

    Private _columnSpan As Integer = 1
    ''' <summary>
    ''' 結合する列数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("セル結合")> _
    <Description("列数")>
    Public Property ColumnSpan As Integer
        Get
            Return _columnSpan
        End Get
        Set(ByVal value As Integer)
            _columnSpan = value
        End Set
    End Property

    Private _backgroundColor As System.Drawing.Color = Color.Empty
    ''' <summary>
    ''' セルの背景色
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セルの背景色")>
    Public Property BackgroundColor As System.Drawing.Color
        Get
            Return _backgroundColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            _backgroundColor = value
        End Set
    End Property

    Private _foreColor As System.Drawing.Color = Color.Empty
    ''' <summary>
    ''' テキストの文字色
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("テキストの文字色")>
    Public Property ForeColor As System.Drawing.Color
        Get
            Return _foreColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            _foreColor = value
        End Set
    End Property


    Private _text As String
    ''' <summary>
    ''' セルに関連付けられたテキスト
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セルに関連付けられたテキストです")>
    Public Property Text As String
        Get
            Return _text
        End Get
        Set(ByVal value As String)
            _text = value
        End Set
    End Property

    Private _textAlign As DataGridViewContentAlignment
    ''' <summary>
    ''' 結合されたセル内でのテキストの位置
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("結合されたセル内のテキストの位置を決定します")>
    Public Property TextAlign As DataGridViewContentAlignment
        Get
            Return _textAlign
        End Get
        Set(ByVal value As DataGridViewContentAlignment)
            _textAlign = value
        End Set
    End Property

    Private _wrapMode As DataGridViewTriState = DataGridViewTriState.NotSet
    ''' <summary>
    ''' セルに含まれるテキスト形式の内容が 1 行に収まらないほど長い場合に、次の行に折り返されるか、
    ''' 切り捨てられるかを示す値を取得または設定する
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("セル内のテキストが一行に収まらない場合にテキストを折り返す")>
    Public Property WrapMode As DataGridViewTriState
        Get
            Return _wrapMode
        End Get
        Set(ByVal value As DataGridViewTriState)
            _wrapMode = value
        End Set
    End Property

    Private _sortVisible As Boolean
    ''' <summary>
    ''' 結合されている列に並び替えがある場合に並び替えの方向を表示する
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("表示")> _
    <Description("結合されている列に並び替えがある場合に並び替えの方向を表示する")>
    Public Property SortVisible As Boolean
        Get
            Return _sortVisible
        End Get
        Set(ByVal value As Boolean)
            _sortVisible = value
        End Set
    End Property
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace ClassLibrary1
{
    class HeaderCell

    {
        private int _row;
        /// 
        /// 行
        /// 
        /// 
        /// 
        /// 
        [Category("セル位置")]
        [Description("行")]
        public int Row
        {
            get { return _row; }
            set { _row = value; }
        }

        private int _column;
        /// 
        /// 列
        /// 
        /// 
        /// 
        /// 
        [Category("セル位置")]
        [Description("列")]
        public int Column
        {
            get { return _column; }
            set { _column = value; }
        }

        private int _rowSpan = 1;
        /// 
        /// 結合する行数
        /// 
        /// 
        /// 
        /// 
        [Category("セル結合")]
        [Description("行数")]
        public int RowSpan
        {
            get { return _rowSpan; }
            set { _rowSpan = value; }
        }

        private int _columnSpan = 1;
        /// 
        /// 結合する列数
        /// 
        /// 
        /// 
        /// 
        [Category("セル結合")]
        [Description("列数")]
        public int ColumnSpan
        {
            get { return _columnSpan; }
            set { _columnSpan = value; }
        }

        private System.Drawing.Color _backgroundColor = Color.Empty;
        /// 
        /// セルの背景色
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セルの背景色")]
        public System.Drawing.Color BackgroundColor
        {
            get { return _backgroundColor; }
            set { _backgroundColor = value; }
        }

        private System.Drawing.Color _foreColor = Color.Empty;
        /// 
        /// テキストの文字色
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("テキストの文字色")]
        public System.Drawing.Color ForeColor
        {
            get { return _foreColor; }
            set { _foreColor = value; }
        }


        private string _text;
        /// 
        /// セルに関連付けられたテキスト
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セルに関連付けられたテキストです")]
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        private DataGridViewContentAlignment _textAlign;
        /// 
        /// 結合されたセル内でのテキストの位置
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("結合されたセル内のテキストの位置を決定します")]
        public DataGridViewContentAlignment TextAlign
        {
            get { return _textAlign; }
            set { _textAlign = value; }
        }

        private DataGridViewTriState _wrapMode = DataGridViewTriState.NotSet;
        /// 
        /// セルに含まれるテキスト形式の内容が 1 行に収まらないほど長い場合に、次の行に折り返されるか、
        /// 切り捨てられるかを示す値を取得または設定する
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("セル内のテキストが一行に収まらない場合にテキストを折り返す")]
        public DataGridViewTriState WrapMode
        {
            get { return _wrapMode; }
            set { _wrapMode = value; }
        }

        private bool _sortVisible;
        /// 
        /// 結合されている列に並び替えがある場合に並び替えの方向を表示する
        /// 
        /// 
        /// 
        /// 
        [Category("表示")]
        [Description("結合されている列に並び替えがある場合に並び替えの方向を表示する")]
        public bool SortVisible
        {
            get { return _sortVisible; }
            set { _sortVisible = value; }
        }
    }
}

次にDataGridViewの継承クラスを作成します。

クラスに以下ののプロパティを追加。
プロパティ意味
ColumnHeaderBorderStyle列ヘッダーセルの境界線の線種
ColumnHeaderRowCount列ヘッダーの行数
ColumnHeaderRowHeight列ヘッダーの行の高さ
HeaderCells列ヘッダーのセル定義

次にOnPaintイベントにヘッダセルの描画処理とセルの結合の描画処理を記述します。

スクロール時、コントロールのサイズ変更時および列の幅が変更された時に直前の描画が
残るのを防ぐために描画領域の無効化をしています。
VB.NET
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing
'Imports MyLibrary.HeaderCell


Public Class CustomHeaderDataGridView
    Inherits System.Windows.Forms.DataGridView

    Private _item As New MyCollection(Me)

    ''' <summary>
    ''' 列ヘッダに表示するCellを設定します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示するCellを設定します")>
    Public ReadOnly Property HeaderCells() As MyCollection
        Get
            Return _item
        End Get
    End Property

    Friend Sub OnCollectionChanged()
        Me.Invalidate()
    End Sub



    ''' <summary>
    ''' コレクションの設定
    ''' </summary>
    ''' <remarks></remarks>
    Public Class MyCollection
        Inherits System.Collections.ObjectModel.Collection(Of HeaderCell)

        Private _parent As CustomHeaderDataGridView

        Friend Sub New(ByVal parent As CustomHeaderDataGridView)
            _parent = parent
        End Sub

        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As HeaderCell)
            MyBase.InsertItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub RemoveItem(ByVal index As Integer)
            MyBase.RemoveItem(index)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As HeaderCell)
            MyBase.SetItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

    End Class


    Private _columnHeaderRowCount As Integer = 1
    ''' <summary>
    ''' 列ヘッダーの行数を設定します
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示する行を設定します")>
    Public Property ColumnHeaderRowCount As Integer
        Get
            Return _columnHeaderRowCount
        End Get
        Set(ByVal value As Integer)



            _columnHeaderRowCount = value

            If value = 0 Then
                _columnHeaderRowCount = 1
            End If

            MyBase.ColumnHeadersHeight = value * ColumnHeaderRowHeight + 2
            MyBase.Refresh()
        End Set
    End Property

    Private _columnHeaderRowHeight As Integer = 17
    ''' <summary>
    ''' 列ヘッダに表示する行の高さ
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに表示する行の高さを設定します")>
    Public Property ColumnHeaderRowHeight As Integer
        Get
            Return _columnHeaderRowHeight
        End Get
        Set(ByVal value As Integer)
            _columnHeaderRowHeight = value

            MyBase.ColumnHeadersHeight = value * ColumnHeaderRowCount + 2
            MyBase.Refresh()
        End Set
    End Property

    ''' <summary>
    ''' 列ヘッダーの境界線の種類
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum HeaderCellBorderStyle
        SingleLine = 0
        DoubleLine = 1
    End Enum

    Private _columnHeaderBorderStyle As HeaderCellBorderStyle = HeaderCellBorderStyle.SingleLine
    ''' <summary>
    ''' 列ヘッダーの線種
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Category("列ヘッダのカスタマイズ")> _
    <Description("列ヘッダに線種を設定します")>
    Public Property ColumnHeaderBorderStyle As HeaderCellBorderStyle
        Get
            Return _columnHeaderBorderStyle
        End Get
        Set(ByVal value As HeaderCellBorderStyle)
            _columnHeaderBorderStyle = value
            MyBase.Refresh()
        End Set
    End Property

    <System.Diagnostics.DebuggerNonUserCode()> _
    Public Sub New()
        MyBase.New()

        'この呼び出しは、コンポーネント デザイナーで必要です。
        InitializeComponent()

        MyBase.DoubleBuffered = True

    End Sub

    'Component は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'コンポーネント デザイナーで必要です。
    Private components As System.ComponentModel.IContainer

    'メモ: 以下のプロシージャはコンポーネント デザイナーで必要です。
    'コンポーネント デザイナーを使って変更できます。
    'コード エディターを使って変更しないでください。
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

    

    ''' <summary>
    ''' 再描画をするとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Try

            
            '---------------------------------------------------------------------------------------------------------
            'ヘッダーセルの描画
            '---------------------------------------------------------------------------------------------------------

            'ヘッダーの行の高さの取得
            Dim rowHeight As Integer = MyBase.ColumnHeadersHeight

            If Me.ColumnHeaderRowCount > 0 Then
                rowHeight = MyBase.ColumnHeadersHeight / Me.ColumnHeaderRowCount
            End If

            '線の太さ
            Dim lineWidth As Integer = 1

            For i = 0 To ColumnCount - 1

                For j = 0 To Me.ColumnHeaderRowCount - 1

                    'グッリドの線
                    Dim gridPen As New Pen(MyBase.GridColor)

                    '背景色
                    Dim backBrash As New SolidBrush(MyBase.ColumnHeadersDefaultCellStyle.BackColor)

                    'くぼみ線
                    Dim whiteBrash As New SolidBrush(Color.White)

                    Try
                        '列ヘッダーの描画領域
                        Dim rect As Rectangle = MyBase.GetCellDisplayRectangle(i, -1, True)

                        '列ヘッダーの描画領域の底部の座標を保存
                        Dim btm As Integer = rect.Bottom

                        'セルの描画領域のY座標
                        Select Case MyBase.BorderStyle
                            Case Windows.Forms.BorderStyle.None
                                rect.Y = rowHeight * j
                            Case Windows.Forms.BorderStyle.FixedSingle
                                rect.Y = rowHeight * j + lineWidth
                            Case Windows.Forms.BorderStyle.Fixed3D
                                rect.Y = rowHeight * j + (lineWidth * 2)
                        End Select

                        'セルの描画領域のX座標
                        rect.X -= lineWidth

                        'セルの描画領域の高さ
                        rect.Height = rowHeight

                        '最下行の場合高さを調整
                        If j = Me.ColumnHeaderRowCount - 1 Then
                            rect.Height = btm - rect.Y - lineWidth
                        End If

                        'セルを囲む線の描画
                        e.Graphics.DrawRectangle(gridPen, rect)


                        'セルの背景色の領域
                        rect.Y += lineWidth
                        rect.X += lineWidth
                        rect.Height -= lineWidth
                        rect.Width -= lineWidth

                        '背景色の描画
                        If ColumnHeaderBorderStyle <> HeaderCellBorderStyle.DoubleLine Then
                            'Single線の場合
                            e.Graphics.FillRectangle(backBrash, rect)
                        Else
                            'くぼみ線の場合
                            'rect.Width -= lineWidth
                            e.Graphics.FillRectangle(whiteBrash, rect)
                            rect.Y += lineWidth
                            rect.X += lineWidth
                            rect.Height -= lineWidth
                            rect.Width -= lineWidth

                            e.Graphics.FillRectangle(backBrash, rect)
                        End If

                        '見出しを最下列に表示
                        If j = Me.ColumnHeaderRowCount - 1 Then
                            Dim text As String = MyBase.Columns(i).HeaderText

                            If MyBase.SortedColumn IsNot Nothing AndAlso MyBase.SortedColumn Is Me.Columns(i) Then
                                If MyBase.SortOrder = Windows.Forms.SortOrder.Ascending Then
 text = text & "  ▼"
                                ElseIf MyBase.SortOrder = Windows.Forms.SortOrder.Descending Then
 text = text & "  ▲"
                                End If
                            End If

                            Dim formatFlg As TextFormatFlags = GetTextFormatFlags(MyBase.ColumnHeadersDefaultCellStyle.Alignment, _
MyBase.ColumnHeadersDefaultCellStyle.WrapMode)

                            TextRenderer.DrawText(e.Graphics, text, MyBase.ColumnHeadersDefaultCellStyle.Font, _
rect, MyBase.ColumnHeadersDefaultCellStyle.ForeColor, _
formatFlg)
                        End If

                    Finally
                        'リソースの解放
                        gridPen.Dispose()
                        backBrash.Dispose()
                        whiteBrash.Dispose()
                    End Try
                Next
            Next


            '---------------------------------------------------------------------------------------------------------
            'ヘッダーのセル結合
            '---------------------------------------------------------------------------------------------------------
            'ヘッダーセル定義の処理
            For i = 0 To Me.HeaderCells.Count - 1

                'セルの結合の開始行がヘッダーの行数より大きい場合は除外
                If HeaderCells(i).Row > Me.ColumnHeaderRowCount - 1 Then
                    Continue For
                End If

                'セルの結合の開始列の列インデックスが列数より大きい場合は除外
                If HeaderCells(i).Column > MyBase.ColumnCount - 1 Then
                    Continue For
                End If

                '描画領域の設定
                Dim rect As Rectangle = Nothing

                '結合する列中のソート状態
                Dim sortText As String = String.Empty

                '結合するセルの各列の幅を取得し描画領域の幅を決める、ソートされている列の場合Textに表示するソート方向の設定
                For j = Me.HeaderCells(i).Column To Me.HeaderCells(i).Column + Me.HeaderCells(i).ColumnSpan - 1

                    '列が画面に表示されていない場合は処理しない
                    If MyBase.Columns(j).Displayed = False Then
                        Continue For
                    End If

                    '列ヘッダーの領域の幅
                    If rect = Nothing Then
                        '結合するセルの開始列の場合
                        rect = MyBase.GetCellDisplayRectangle(j, -1, True)
                    Else
                        '結合するセルの2列目以降の場合
                        rect.Width += MyBase.GetCellDisplayRectangle(j, -1, True).Width
                    End If


                    'ソート列の場合
                    If HeaderCells(i).SortVisible = True AndAlso MyBase.SortedColumn IsNot Nothing AndAlso MyBase.SortedColumn Is MyBase.Columns(j) Then
                        If MyBase.SortOrder = Windows.Forms.SortOrder.Ascending Then
                            sortText = "  ▼"
                        ElseIf MyBase.SortOrder = Windows.Forms.SortOrder.Descending Then
                            sortText = "  ▲"
                        End If
                    End If

                Next

                '結合するセルが画面中に無い場合
                If rect = Nothing Then
                    Continue For
                End If

                '結合する行がヘッダー行数より大きい場合
                Dim rowSapn As Integer = Me.HeaderCells(i).RowSpan
                If rowSapn > ColumnHeaderRowCount Then
                    rowSapn = ColumnHeaderRowCount
                End If

                '列ヘッダーの描画領域の底部の座標を保存
                Dim btm As Integer = rect.Bottom

                '結合するセルの描画領域のY座標
                Select Case MyBase.BorderStyle
                    Case Windows.Forms.BorderStyle.None
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row)
                    Case Windows.Forms.BorderStyle.FixedSingle
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row) + lineWidth
                    Case Windows.Forms.BorderStyle.Fixed3D
                        rect.Y = rowHeight * (Me.HeaderCells(i).Row) + (lineWidth * 2)
                End Select

                '結合するセルの描画領域のX座標
                rect.X -= lineWidth

                '結合するセルの描画領域の高さ
                rect.Height = rowHeight * rowSapn

                '最下行の場合は描画領域の高さを調整する
                If Me.HeaderCells(i).Row + rowSapn = Me.ColumnHeaderRowCount Then
                    rect.Height = btm - rect.Y - lineWidth
                End If

                'グッリドの線
                Dim gridPen As New Pen(MyBase.GridColor)

                '背景色の取得
                Dim backgroundColor As System.Drawing.Color = MyBase.ColumnHeadersDefaultCellStyle.BackColor
                'セルの背景色が設定されている場合
                If Not Me.HeaderCells(i).BackgroundColor = Color.Empty Then
                    backgroundColor = Me.HeaderCells(i).BackgroundColor
                End If

                '背景色
                Dim backBrash As New SolidBrush(backgroundColor)

                'くぼみ線
                Dim whiteBrash As New SolidBrush(Color.White)

                Try

                    '枠線の描画
                    e.Graphics.DrawRectangle(gridPen, rect)


                    '結合セルの背景色の描画領域の設定
                    rect.Y += lineWidth
                    rect.X += lineWidth
                    rect.Height -= lineWidth
                    rect.Width -= lineWidth


                    '背景色の描画
                    If ColumnHeaderBorderStyle = HeaderCellBorderStyle.SingleLine Then
                        'Singleの場合
                        e.Graphics.FillRectangle(backBrash, rect)
                    Else
                        'くぼみ線の場合
                        e.Graphics.FillRectangle(whiteBrash, rect)
                        rect.Y += lineWidth
                        rect.X += lineWidth
                        rect.Height -= lineWidth
                        rect.Width -= lineWidth

                        e.Graphics.FillRectangle(backBrash, rect)
                    End If


                    'テキストの描画
                    Dim foreColor As System.Drawing.Color = MyBase.ColumnHeadersDefaultCellStyle.ForeColor
                    If Not Me.HeaderCells(i).ForeColor = Color.Empty Then
                        foreColor = Me.HeaderCells(i).ForeColor
                    End If

                    Dim formatFlg As TextFormatFlags = GetTextFormatFlags(Me.HeaderCells(i).TextAlign, Me.HeaderCells(i).WrapMode)

                    TextRenderer.DrawText(e.Graphics, Me.HeaderCells(i).Text & sortText, MyBase.ColumnHeadersDefaultCellStyle.Font, _
rect, foreColor, formatFlg)

                Finally
                    'リソースの解放
                    gridPen.Dispose()
                    backBrash.Dispose()
                    whiteBrash.Dispose()
                End Try
            Next

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' 指定のスタイルから描写するテキストのスタイルを取得する
    ''' </summary>
    ''' <param name="alignment">テキストのスタイル</param>
    ''' <param name="wrapMode">折り返</param>
    ''' <remarks>描写するテキストのスタイル</remarks>
    Private Function GetTextFormatFlags(ByVal alignment As DataGridViewContentAlignment,
ByVal wrapMode As DataGridViewTriState) As TextFormatFlags
        Try
            ''文字の描画
            Dim formatFlg As TextFormatFlags = TextFormatFlags.Right Or TextFormatFlags.VerticalCenter Or TextFormatFlags.EndEllipsis

            '表示位置
            Select Case alignment
                Case DataGridViewContentAlignment.BottomCenter
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.BottomLeft
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.BottomRight
                    formatFlg = TextFormatFlags.Bottom Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleCenter
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleLeft
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.MiddleRight
                    formatFlg = TextFormatFlags.VerticalCenter Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopCenter
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopLeft
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.Left Or TextFormatFlags.EndEllipsis
                Case DataGridViewContentAlignment.TopRight
                    formatFlg = TextFormatFlags.Top Or TextFormatFlags.Right Or TextFormatFlags.EndEllipsis
            End Select


            '折り返し
            Select Case wrapMode
                Case DataGridViewTriState.False
                Case DataGridViewTriState.NotSet
                Case DataGridViewTriState.True
                    formatFlg = formatFlg Or TextFormatFlags.WordBreak
            End Select

            Return formatFlg

        Catch ex As Exception
            Throw
        End Try
    End Function

    ''' <summary>
    ''' セルを結合する対象の列の描画領域の無効化
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InvalidateUnitColumns()
        Try

            Dim hRect As Rectangle = MyBase.DisplayRectangle
            hRect.Height = MyBase.ColumnHeadersHeight + 1
            MyBase.Invalidate(hRect)

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' スクロールが実行されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnScroll(ByVal e As System.Windows.Forms.ScrollEventArgs)
        MyBase.OnScroll(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' サイズが変更されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnSizeChanged(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try

    End Sub

    ''' <summary>
    ''' 列の幅が変更されたとき
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnColumnWidthChanged(ByVal e As System.Windows.Forms.DataGridViewColumnEventArgs)
        MyBase.OnColumnWidthChanged(e)

        Try
            InvalidateUnitColumns()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' 行の境界線がダブルクリックされた時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnRowDividerDoubleClick(ByVal e As System.Windows.Forms.DataGridViewRowDividerDoubleClickEventArgs)
        MyBase.OnRowDividerDoubleClick(e)

        Try
            '行ヘッダーの境界線がダブルクリックされたへっだーの高さを整える
            If e.RowIndex = -1 Then
                MyBase.ColumnHeadersHeight = Me.ColumnHeaderRowCount * Me.ColumnHeaderRowHeight + 2
            End If
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' マウスのボタンが押された時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDown(e)

        Try
            '列幅、行高を調整するドラグ線を見えるようにするためにダブルバッファを解除する
            MyBase.DoubleBuffered = False
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' マウスのボタンが離された時
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseUp(e)

        Try
            'OnMouseDownイベントで解除されたダブルバッファを適用する
            MyBase.DoubleBuffered = True
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;


namespace ClassLibrary1
{
    class CustomHeaderDataGridView : System.Windows.Forms.DataGridView
    {
        private MyCollection _item = null;

        /// 
        /// 列ヘッダに表示するCellを設定します
        /// 
        /// 
        /// 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示するCellを設定します")]
        public MyCollection HeaderCells
        {
            get { return _item; }
        }

        internal void OnCollectionChanged()
        {
            this.Invalidate();
        }

        /// 
        /// コレクションの設定
        /// 
        /// 
        public class MyCollection : System.Collections.ObjectModel.Collection<HeaderCell>
        {

            private CustomHeaderDataGridView _parent;

            internal MyCollection(CustomHeaderDataGridView parent)
            {
                _parent = parent;
            }

            protected override void ClearItems()
            {
                base.ClearItems();
                _parent.OnCollectionChanged();
            }

            protected override void InsertItem(int index, HeaderCell item)
            {
                base.InsertItem(index, item);
                _parent.OnCollectionChanged();
            }

            protected override void RemoveItem(int index)
            {
                base.RemoveItem(index);
                _parent.OnCollectionChanged();
            }

            protected override void SetItem(int index, HeaderCell item)
            {
                base.SetItem(index, item);
                _parent.OnCollectionChanged();
            }

        }

        private int _columnHeaderRowCount = 1;
        /// 
        /// 列ヘッダーの行数を設定します
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示する行を設定します")]
        public int ColumnHeaderRowCount
        {
            get { return _columnHeaderRowCount; }
            set
            {
                _columnHeaderRowCount = value;

                if (value == 0)
                {
                    _columnHeaderRowCount = 1;
                }

                base.ColumnHeadersHeight = value * ColumnHeaderRowHeight + 2;
                base.Refresh();
            }
        }

        private int _columnHeaderRowHeight = 17;
        // 
        /// 列ヘッダに表示する行の高さ
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに表示する行の高さを設定します")]
        public int ColumnHeaderRowHeight
        {
            get { return _columnHeaderRowHeight; }
            set
            {
                _columnHeaderRowHeight = value;

                base.ColumnHeadersHeight = value * ColumnHeaderRowCount + 2;
                base.Refresh();
            }
        }

        /// 
        /// 列ヘッダーの境界線の種類
        /// 
        /// 
        public enum HeaderCellBorderStyle
        {
            SingleLine = 0,
            DoubleLine = 1
        }

        private HeaderCellBorderStyle _columnHeaderBorderStyle = HeaderCellBorderStyle.SingleLine;
        /// 
        /// 列ヘッダーの線種
        /// 
        /// 
        /// 
        /// 
        [Category("列ヘッダのカスタマイズ")]
        [Description("列ヘッダに線種を設定します")]
        public HeaderCellBorderStyle ColumnHeaderBorderStyle
        {
            get { return _columnHeaderBorderStyle; }
            set
            {
                _columnHeaderBorderStyle = value;
                base.Refresh();
            }
        }

        [System.Diagnostics.DebuggerNonUserCode()]
        public CustomHeaderDataGridView()
            : base()
        {
            //この呼び出しは、コンポーネント デザイナーで必要です。
            InitializeComponent();

            this._item = new MyCollection(this);
            base.DoubleBuffered = true;

        }


        //Component は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
        [System.Diagnostics.DebuggerNonUserCode()]
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing && components != null)
                {
                    components.Dispose();
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }

        //コンポーネント デザイナーで必要です。
        private System.ComponentModel.IContainer components;

        //メモ: 以下のプロシージャはコンポーネント デザイナーで必要です。
        //コンポーネント デザイナーを使って変更できます。
        //コード エディターを使って変更しないでください。
        [System.Diagnostics.DebuggerStepThrough()]
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }





        /// 再描画をするとき
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            try
            {


                //---------------------------------------------------------------------------------------------------------
                //ヘッダーセルの描画
                //---------------------------------------------------------------------------------------------------------

                //ヘッダーの行の高さの取得
                int rowHeight = base.ColumnHeadersHeight;

                if (this.ColumnHeaderRowCount > 0)
                {
                    rowHeight = base.ColumnHeadersHeight / this.ColumnHeaderRowCount;
                }

                //線の太さ
                int lineWidth = 1;

                for (int i = 0; i <= ColumnCount - 1; i++)
                {

                    for (int j = 0; j <= this.ColumnHeaderRowCount - 1; j++)
                    {

                        //グッリドの線
                        Pen gridPen = new Pen(base.GridColor);

                        //背景色
                        SolidBrush backBrash = new SolidBrush(base.ColumnHeadersDefaultCellStyle.BackColor);

                        //くぼみ線
                        SolidBrush whiteBrash = new SolidBrush(Color.White);

                        try
                        {
                            //列ヘッダーの描画領域
                            Rectangle rect = base.GetCellDisplayRectangle(i, -1, true);

                            //列ヘッダーの描画領域の底部の座標を保存
                            int btm = rect.Bottom;

                            //セルの描画領域のY座標
                            switch (base.BorderStyle)
                            {
                                case BorderStyle.None:
 rect.Y = rowHeight * j;
 break;
                                case BorderStyle.FixedSingle:
 rect.Y = rowHeight * j + lineWidth;
 break;
                                case BorderStyle.Fixed3D:
 rect.Y = rowHeight * j + (lineWidth * 2);
 break;
                            }

                            //セルの描画領域のX座標
                            rect.X -= lineWidth;

                            //セルの描画領域の高さ
                            rect.Height = rowHeight;

                            //最下行の場合高さを調整
                            if (j == this.ColumnHeaderRowCount - 1)
                            {
                                rect.Height = btm - rect.Y - lineWidth;
                            }

                            //セルを囲む線の描画
                            e.Graphics.DrawRectangle(gridPen, rect);


                            //セルの背景色の領域
                            rect.Y += lineWidth;
                            rect.X += lineWidth;
                            rect.Height -= lineWidth;
                            rect.Width -= lineWidth;

                            //背景色の描画
                            if (ColumnHeaderBorderStyle != HeaderCellBorderStyle.DoubleLine)
                            {
                                //Single線の場合
                                e.Graphics.FillRectangle(backBrash, rect);
                            }
                            else
                            {
                                //くぼみ線の場合
                                //rect.Width -= lineWidth
                                e.Graphics.FillRectangle(whiteBrash, rect);
                                rect.Y += lineWidth;
                                rect.X += lineWidth;
                                rect.Height -= lineWidth;
                                rect.Width -= lineWidth;

                                e.Graphics.FillRectangle(backBrash, rect);
                            }

                            //見出しを最下列に表示
                            if (j == this.ColumnHeaderRowCount - 1)
                            {
                                string text = base.Columns[i].HeaderText;

                                if (base.SortedColumn != null && object.ReferenceEquals(base.SortedColumn, this.Columns[i]))
                                {
 if (base.SortOrder == SortOrder.Ascending)
 {
text = text + " ▼";
 }
 else if (base.SortOrder == SortOrder.Descending)
 {
text = text + " ▲";
 }
                                }

                                TextFormatFlags formatFlg = GetTextFormatFlags(base.ColumnHeadersDefaultCellStyle.Alignment, base.ColumnHeadersDefaultCellStyle.WrapMode);

                                TextRenderer.DrawText(e.Graphics, text, base.ColumnHeadersDefaultCellStyle.Font, rect, base.ColumnHeadersDefaultCellStyle.ForeColor, formatFlg);
                            }

                        }
                        finally
                        {
                            //リソースの解放
                            gridPen.Dispose();
                            backBrash.Dispose();
                            whiteBrash.Dispose();
                        }
                    }
                }

                //---------------------------------------------------------------------------------------------------------
                //ヘッダーのセル結合
                //---------------------------------------------------------------------------------------------------------
                //ヘッダーセル定義の処理
                for (int i = 0; i <= this.HeaderCells.Count - 1; i++)
                {

                    //セルの結合の開始行がヘッダーの行数より大きい場合は除外
                    if (HeaderCells[i].Row > this.ColumnHeaderRowCount - 1)
                    {
                        continue;
                    }

                    //セルの結合の開始列の列インデックスが列数より大きい場合は除外
                    if (HeaderCells[i].Column > base.ColumnCount - 1)
                    {
                        continue;
                    }

                    //描画領域の設定
                    Rectangle rect = Rectangle.Empty;

                    //結合する列中のソート状態
                    string sortText = string.Empty;

                    //結合するセルの各列の幅を取得し描画領域の幅を決める、ソートされている列の場合Textに表示するソート方向の設定
                    for (int j = this.HeaderCells[i].Column; j <= this.HeaderCells[i].Column + this.HeaderCells[i].ColumnSpan - 1; j++)
                    {

                        //列が画面に表示されていない場合は処理しない
                        if (base.Columns[j].Displayed == false)
                        {
                            continue;
                        }

                        //列ヘッダーの領域の幅
                        if (rect.IsEmpty)
                        {
                            //結合するセルの開始列の場合
                            rect = base.GetCellDisplayRectangle(j, -1, true);
                        }
                        else
                        {
                            //結合するセルの2列目以降の場合
                            rect.Width += base.GetCellDisplayRectangle(j, -1, true).Width;
                        }


                        //ソート列の場合
                        if (HeaderCells[i].SortVisible == true && base.SortedColumn != null && object.ReferenceEquals(base.SortedColumn, base.Columns[j]))
                        {
                            if (base.SortOrder == SortOrder.Ascending)
                            {
                                sortText = " ▼";
                            }
                            else if (base.SortOrder == SortOrder.Descending)
                            {
                                sortText = " ▲";
                            }
                        }

                    }

                    //結合するセルが画面中に無い場合
                    if (rect == null)
                    {
                        continue;
                    }

                    //結合する行がヘッダー行数より大きい場合
                    int rowSapn = this.HeaderCells[i].RowSpan;
                    if (rowSapn > ColumnHeaderRowCount)
                    {
                        rowSapn = ColumnHeaderRowCount;
                    }

                    //列ヘッダーの描画領域の底部の座標を保存
                    int btm = rect.Bottom;

                    //結合するセルの描画領域のY座標
                    switch (base.BorderStyle)
                    {
                        case BorderStyle.None:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row);
                            break;
                        case BorderStyle.FixedSingle:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row) + lineWidth;
                            break;
                        case BorderStyle.Fixed3D:
                            rect.Y = rowHeight * (this.HeaderCells[i].Row) + (lineWidth * 2);
                            break;
                    }

                    //結合するセルの描画領域のX座標
                    rect.X -= lineWidth;

                    //結合するセルの描画領域の高さ
                    rect.Height = rowHeight * rowSapn;

                    //最下行の場合は描画領域の高さを調整する
                    if (this.HeaderCells[i].Row + rowSapn == this.ColumnHeaderRowCount)
                    {
                        rect.Height = btm - rect.Y - lineWidth;
                    }

                    //グッリドの線
                    Pen gridPen = new Pen(base.GridColor);

                    //背景色の取得
                    System.Drawing.Color backgroundColor = base.ColumnHeadersDefaultCellStyle.BackColor;
                    //セルの背景色が設定されている場合
                    if (!(this.HeaderCells[i].BackgroundColor == Color.Empty))
                    {
                        backgroundColor = this.HeaderCells[i].BackgroundColor;
                    }

                    //背景色
                    SolidBrush backBrash = new SolidBrush(backgroundColor);

                    //くぼみ線
                    SolidBrush whiteBrash = new SolidBrush(Color.White);

                    try
                    {

                        //枠線の描画
                        e.Graphics.DrawRectangle(gridPen, rect);


                        //結合セルの背景色の描画領域の設定
                        rect.Y += lineWidth;
                        rect.X += lineWidth;
                        rect.Height -= lineWidth;
                        rect.Width -= lineWidth;


                        //背景色の描画
                        if (ColumnHeaderBorderStyle == HeaderCellBorderStyle.SingleLine)
                        {
                            //Singleの場合
                            e.Graphics.FillRectangle(backBrash, rect);
                        }
                        else
                        {
                            //くぼみ線の場合
                            e.Graphics.FillRectangle(whiteBrash, rect);
                            rect.Y += lineWidth;
                            rect.X += lineWidth;
                            rect.Height -= lineWidth;
                            rect.Width -= lineWidth;

                            e.Graphics.FillRectangle(backBrash, rect);
                        }


                        //テキストの描画
                        System.Drawing.Color foreColor = base.ColumnHeadersDefaultCellStyle.ForeColor;
                        if (!(this.HeaderCells[i].ForeColor == Color.Empty))
                        {
                            foreColor = this.HeaderCells[i].ForeColor;
                        }

                        TextFormatFlags formatFlg = GetTextFormatFlags(this.HeaderCells[i].TextAlign, this.HeaderCells[i].WrapMode);

                        TextRenderer.DrawText(e.Graphics, this.HeaderCells[i].Text + sortText, base.ColumnHeadersDefaultCellStyle.Font, rect, foreColor, formatFlg);

                    }
                    finally
                    {
                        //リソースの解放
                        gridPen.Dispose();
                        backBrash.Dispose();
                        whiteBrash.Dispose();
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }


        /// <summary>
        /// 指定のスタイルから描写するテキストのスタイルを取得する
        /// </summary>
        /// <param name="alignment">テキストのスタイル</param>
        /// <param name="wrapMode">折り返</param>
        /// <remarks>描写するテキストのスタイル</remarks>
        private TextFormatFlags GetTextFormatFlags(DataGridViewContentAlignment alignment, DataGridViewTriState wrapMode)
        {
            try
            {
                //'文字の描画
                TextFormatFlags formatFlg = TextFormatFlags.Right | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis;

                //表示位置
                switch (alignment)
                {
                    case DataGridViewContentAlignment.BottomCenter:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.BottomLeft:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.BottomRight:
                        formatFlg = TextFormatFlags.Bottom | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleCenter:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleLeft:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.MiddleRight:
                        formatFlg = TextFormatFlags.VerticalCenter | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopCenter:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopLeft:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.Left | TextFormatFlags.EndEllipsis;
                        break;
                    case DataGridViewContentAlignment.TopRight:
                        formatFlg = TextFormatFlags.Top | TextFormatFlags.Right | TextFormatFlags.EndEllipsis;
                        break;
                }


                //折り返し
                switch (wrapMode)
                {
                    case DataGridViewTriState.False:
                        break;
                    case DataGridViewTriState.NotSet:
                        break;
                    case DataGridViewTriState.True:
                        formatFlg = formatFlg | TextFormatFlags.WordBreak;
                        break;
                }

                return formatFlg;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// セルを結合する対象の列の描画領域の無効化
        /// </summary>
        /// <remarks></remarks>
        private void InvalidateUnitColumns()
        {
            try
            {

                Rectangle hRect = base.DisplayRectangle;
                hRect.Height = base.ColumnHeadersHeight + 1;
                base.Invalidate(hRect);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// スクロールが実行されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnScroll(System.Windows.Forms.ScrollEventArgs e)
        {
            base.OnScroll(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// サイズが変更されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnSizeChanged(System.EventArgs e)
        {
            base.OnSizeChanged(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

        /// <summary>
        /// 列の幅が変更されたとき
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnColumnWidthChanged(System.Windows.Forms.DataGridViewColumnEventArgs e)
        {
            base.OnColumnWidthChanged(e);

            try
            {
                InvalidateUnitColumns();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 行の境界線がダブルクリックされた時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnRowDividerDoubleClick(System.Windows.Forms.DataGridViewRowDividerDoubleClickEventArgs e)
        {
            base.OnRowDividerDoubleClick(e);

            try
            {
                //行ヘッダーの境界線がダブルクリックされたへっだーの高さを整える
                if (e.RowIndex == -1)
                {
                    base.ColumnHeadersHeight = this.ColumnHeaderRowCount * this.ColumnHeaderRowHeight + 2;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// マウスのボタンが押された時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            base.OnMouseDown(e);

            try
            {
                //列幅、行高を調整するドラグ線を見えるようにするためにダブルバッファを解除する
                base.DoubleBuffered = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// マウスのボタンが離された時
        /// </summary>
        /// <param name="e"></param>
        /// <remarks></remarks>
        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            base.OnMouseUp(e);

            try
            {
                //OnMouseDownイベントで解除されたダブルバッファを適用する
                base.DoubleBuffered = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}