昨日 の MaskedTextBox を使ったやつを
えムナウさんのアドバイスを受けて、ちょっと修正しました。(MaskedCell クラスの InitializeEditingControl と Clone)
あと、DataGridViewTextBoxEditingControl クラスには AutoComplete に関するプロパティがあるのに、DataGridViewTextBoxColumn? のどこで設定するのか解らなかったので
昨日のと似たような手順でオートコンプリート可能な Text 列の AutoCompletableTextColumn を実装してみました。
C# MVP の Frank Dzaebel さんのページ に DataGridView の DragDrop に関する面白そうなのを見つけたので VB で実装してみました。
あと、えムナウさんの DataGridViewコントロール-CellにTabStop機能を実装する も VB で実装してみました。
疲れました。
DataGridView はまだまだ遊べそうな感じですが、とりあえず DataGridView はこれでおしまいにしようと思います。
■参考文献
DataGridView Drag Drop(Homepage von Frank Dzaebel)
DataGridViewコントロール-CellにTabStop機能を実装する(えムナウさん)
以下、DataGridView 関連で参考になるページ
DataGridViewコントロール(えムナウさん)
Visual Basic Station - Tips - 継承コントロールの作り方(うなまなさん)
Visual Basic Station - Tips - DataGridViewのCell移動をEnterで(うなまなさん)
Visual Basic Station - Tips - DataGridViewスクロール制御(うなまなさん)
Visual Basic Station - Tips - CSVファイルをDataGridViewに表示(うなまなさん)
Visual Basic Station - Tips - DataGridViewのCellイベント(うなまなさん)
Visual Basic Station - Tips - DataGridViewのリンクセルを見やすく(うなまなさん)
Visual Basic Station - Tips - DataGridViewマウス右ボタンで選択(うなまなさん)
なっちゃんのプログラミングTips: DataGridViewの行ヘッダに行番号を表示させるには
GridView コントロールのイベントに関する調査
カスタム データ バインド
カスタム データ バインド (第 2 部)
DataGridView 列ヘッダー セルのドロップダウン フィルタ一覧を作成する
■実行画像
オートコンプリート
Public Class DataGridViewTest
Private Sub DataGridViewTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Size = New Size(600, 300)
'' TabControl に DataGridView を描画します。
Dim tabCntrl As TabControl = New TabControl
Me.Controls.Add(tabCntrl)
tabCntrl.Dock = DockStyle.Fill
tabCntrl.TabPages.Clear()
' TabPage の追加(2006.12.19 DataGridView(System.Windows.Forms.DataGridView)その1参照)
Dim dgView1 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DataGridViewコントロール-内部コントロールの種類", dgView1)
Me.DataGridViewコントロール_内部コントロールの種類(dgView1)
' TabPage の追加(2006.12.20 DataGridView(System.Windows.Forms.DataGridView)その2参照)
Dim dgView2 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DataGridViewコントロール-バインド出来るデータソース", dgView2)
Me.DataGridViewコントロール_バインド出来るデータソース(dgView2)
' TabPage の追加(2006.12.20 DataGridView(System.Windows.Forms.DataGridView)その2参照)
Dim dgView3 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DataGridViewコントロール-DataGridViewCellStyleクラス", dgView3)
Me.DataGridViewコントロール_DataGridViewCellStyleクラス(dgView3)
' TabPage の追加(2006.12.20 DataGridView(System.Windows.Forms.DataGridView)その2参照)
Dim dgView4 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DataGridViewコントロール-行を固定する", dgView4)
Me.DataGridViewコントロール_行を固定する(dgView4)
' TabPage の追加(2006.12.21 DataGridView(System.Windows.Forms.DataGridView)その3参照)
Dim dgView5 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DataGridViewコントロール-行・列を固定する", dgView5)
Me.DataGridViewコントロール_行・列を固定する(dgView5)
' TabPage の追加(2006.12.21 DataGridView(System.Windows.Forms.DataGridView)その3参照)
Dim dgView6 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "Mask列を追加する", dgView6)
Me.Mask列を追加する(dgView6)
' TabPage の追加(2006.12.22)
Dim dgView7 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "DragDropする", dgView7)
Me.DragDropする(dgView7)
' TabPage の追加(2006.12.22)
Dim dgView8 As DataGridView = New DataGridView
Me.AddTabPage(tabCntrl, "オートコンプリート", dgView8)
Me.オートコンプリート(dgView8)
' TabPage の追加(2006.12.22)
Dim dgView9 As TabStopDataGridView = New TabStopDataGridView
Me.AddTabPage(tabCntrl, "TabStopByMnow", dgView9)
Me.TabStopByMnow(dgView9)
tabCntrl.SelectedIndex = tabCntrl.TabPages.Count - 1
End Sub
Private Sub TabStopByMnow(ByVal dgView As TabStopDataGridView)
dgView.Columns.Add(New TabStopTextBoxColumn())
dgView.Columns.Add(New TabStopTextBoxColumn())
dgView.Columns.Add(New TabStopTextBoxColumn())
dgView.Columns.Add(New TabStopTextBoxColumn())
dgView.Columns.Add(New TabStopTextBoxColumn())
dgView.Rows.Add(New String() {"A", "0", "B", "1", "C"})
dgView.Rows.Add(New String() {"D", "2", "E", "3", "F"})
dgView.Rows.Add(New String() {"G", "4", "H", "5", "I"})
dgView.Rows.Add(New String() {"J", "6", "K", "7", "L"})
dgView.Rows.Add(New String() {"M", "8", "N", "9", "O"})
dgView.Rows.Add(New String() {"P", "10", "Q", "11", "R"})
' アルファベットのセルにだけ止まるにする
For Each row As DataGridViewRow In dgView.Rows
DirectCast(row.Cells(1), ISupportTabStop).TabStop = False
DirectCast(row.Cells(3), ISupportTabStop).TabStop = False
Next
End Sub
Private Sub オートコンプリート(ByVal dgView As DataGridView)
Dim col As AutoCompletableTextColumn = New AutoCompletableTextColumn()
col.HeaderText = "Test"
col.AutoCompleteMode = AutoCompleteMode.Suggest
col.AutoCompleteSource = AutoCompleteSource.FileSystem
col.Width = 200
dgView.Columns.Add(col)
Dim customSourceCol As AutoCompletableTextColumn = New AutoCompletableTextColumn()
customSourceCol.AutoCompleteCustomSource = New AutoCompleteStringCollection
customSourceCol.AutoCompleteCustomSource.AddRange(New String() {"fujiko", "eden", "otto"})
customSourceCol.AutoCompleteMode = AutoCompleteMode.SuggestAppend
customSourceCol.AutoCompleteSource = AutoCompleteSource.CustomSource
dgView.Columns.Add(customSourceCol)
dgView.RowCount = 5
dgView.Rows(0).Cells(0).Value = My.Computer.FileSystem.SpecialDirectories.MyDocuments
End Sub
Private Sub DragDropする(ByVal dgView As DataGridView)
' なんか適当なデータをバインドする
Dim ds As DataSet = Me.CreateWankumaDataset()
dgView.DataSource = ds
dgView.DataMember = ds.Tables(0).TableName
ds.Tables(0).Columns.RemoveAt(0) ' 読み取り専用列はだめ
dgView.AllowDrop = True
dgView.SelectionMode = DataGridViewSelectionMode.FullRowSelect
AddHandler dgView.MouseMove, AddressOf Me.DragDropableGridView_MouseMove
AddHandler dgView.MouseDown, AddressOf Me.DragDropableGridView_MouseDown
AddHandler dgView.DragDrop, AddressOf Me.DragDropableGridView_DragDrop
AddHandler dgView.DragOver, AddressOf Me.DragDropableGridView_DragOver
End Sub
Private m_dragBoxSrc As Rectangle
Private m_rowIndexSrc As Integer
Private m_rowIndexTar As Integer
Private Function IsCellOrRowHeader(ByVal x As Integer, ByVal y As Integer, ByVal dgview As DataGridView) As Boolean
Dim dgt As DataGridViewHitTestType = dgview.HitTest(x, y).Type
Return (dgt = DataGridViewHitTestType.Cell OrElse dgt = DataGridViewHitTestType.RowHeader)
End Function
Private Sub DragDropableGridView_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim dgview As DataGridView = DirectCast(sender, DataGridView)
Me.m_rowIndexSrc = dgview.HitTest(e.X, e.Y).RowIndex
If Me.m_rowIndexSrc <> -1 Then
Dim dragSize As Size = SystemInformation.DragSize
Me.m_dragBoxSrc = New Rectangle(New Point(e.X, e.Y), dragSize)
Else
Me.m_dragBoxSrc = Rectangle.Empty
End If
End Sub
Private Sub DragDropableGridView_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim dgview As DataGridView = DirectCast(sender, DataGridView)
If (e.Button And Windows.Forms.MouseButtons.Left) = Windows.Forms.MouseButtons.Left Then
If Not Me.IsCellOrRowHeader(e.X, e.Y, dgview) AndAlso Me.m_rowIndexSrc >= 0 Then
Dim dropEffect As DragDropEffects = _
dgview.DoDragDrop(dgview.Rows(Me.m_rowIndexSrc), DragDropEffects.None)
Return
End If
If Me.m_dragBoxSrc <> Rectangle.Empty AndAlso _
Not Me.m_dragBoxSrc.Contains(e.X, e.Y) Then
Dim dropEffect As DragDropEffects = _
dgview.DoDragDrop(dgview.Rows(Me.m_rowIndexSrc), DragDropEffects.Move)
End If
End If
End Sub
Private Sub DragDropableGridView_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
Dim dgview As DataGridView = DirectCast(sender, DataGridView)
Dim clientPoint As Point = dgview.PointToClient(New Point(e.X, e.Y))
Me.m_rowIndexTar = dgview.HitTest(clientPoint.X, clientPoint.Y).RowIndex
If e.Effect = DragDropEffects.Move Then
Dim rowToMove As DataGridViewRow = DirectCast(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)
Me.MoveRow(Me.m_rowIndexSrc, Me.m_rowIndexTar, dgview)
End If
End Sub
Private Sub SwapCell(ByVal c As Integer, ByVal srcRow As Integer, ByVal tarRow As Integer, ByRef tmp0 As Object, ByRef tmp1 As Object, ByVal dgView As DataGridView)
Dim srcCell As DataGridViewCell = dgView.Rows(srcRow).Cells(c)
Dim tarCell As DataGridViewCell = dgView.Rows(tarRow).Cells(c)
tmp0 = tarCell.Value
tmp1 = srcCell.Value
tarCell.Value = tmp1
End Sub
Private Sub MoveRow(ByVal srcRow As Integer, ByVal tarRow As Integer, ByVal dgView As DataGridView)
Dim cellCount As Integer = dgView.Rows(srcRow).Cells.Count
For c As Integer = 0 To cellCount - 1
Me.ShiftRows(srcRow, tarRow, c, dgView)
Next
End Sub
Private Sub ShiftRows(ByVal srcRow As Integer, ByVal tarRow As Integer, ByVal c As Integer, ByVal dgView As DataGridView)
Dim tmp0 As Object = Nothing
Dim tmp1 As Object = Nothing
Me.SwapCell(c, srcRow, tarRow, tmp0, tmp1, dgView)
Dim delta As Integer = CInt(IIf(tarRow < srcRow, 1, -1))
Dim r As Integer = tarRow + delta
While (r <> srcRow + delta)
tmp1 = dgView.Rows(r).Cells(c).Value
dgView.Rows(r).Cells(c).Value = tmp0
tmp0 = tmp1
r += delta
End While
dgView.Rows(tarRow).Selected = True
dgView.CurrentCell = dgView.Rows(tarRow).Cells(0)
End Sub
Private Sub DragDropableGridView_DragOver(ByVal sender As Object, ByVal e As DragEventArgs)
Dim dgview As DataGridView = DirectCast(sender, DataGridView)
Dim p As Point = dgview.PointToClient(New Point(e.X, e.Y))
Dim dgt As DataGridViewHitTestType = dgview.HitTest(p.X, p.Y).Type
If Me.IsCellOrRowHeader(p.X, p.Y, dgview) Then
e.Effect = DragDropEffects.Move
Else
e.Effect = DragDropEffects.None
End If
End Sub
#Region "Private Sub DataGridViewコントロール_行を固定する"
DataGridView(System.Windows.Forms.DataGridView)その3参照
#End Region
#Region "Private Sub DataGridViewコントロール_行・列を固定する"
DataGridView(System.Windows.Forms.DataGridView)その3参照
#End Region
Private Sub Mask列を追加する(ByVal dgView As DataGridView)
Dim maskCol As MaskedColumn = New MaskedColumn()
maskCol.Mask = "000-0000"
dgView.Columns.Add(maskCol)
dgView.RowCount = 5
End Sub
#Region "Private Sub DataGridViewコントロール_DataGridViewCellStyleクラス"
DataGridView(System.Windows.Forms.DataGridView)その2参照
#End Region
#Region "Private Sub CustomCellPaint"
DataGridView(System.Windows.Forms.DataGridView)その2参照
#End Region
#Region "Private Sub DataGridViewコントロール_バインド出来るデータソース"
DataGridView(System.Windows.Forms.DataGridView)その2参照
#End Region
#Region "Private Sub DataGridViewコントロール_内部コントロールの種類"
DataGridView(System.Windows.Forms.DataGridView)その1参照
#End Region
#Region "Private Sub OnCellContentClick"
DataGridView(System.Windows.Forms.DataGridView)その1参照
#End Region
#Region "Private Sub AddTabPage"
DataGridView(System.Windows.Forms.DataGridView)その1参照
#End Region
#Region "Private Function CreateWankumaDataset"
DataGridView(System.Windows.Forms.DataGridView)その2参照
#End Region
End Class
#Region "Public Class Pet"
DataGridView(System.Windows.Forms.DataGridView)その2参照
#End Region
#Region "MaskedTextBox 列"
Public Class MaskedEditingControl
Inherits MaskedTextBox
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return MyBase.Text
End Get
Set(ByVal value As Object)
If TypeOf value Is [String] Then
MyBase.Text = Convert.ToString(value)
End If
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return MyBase.Text
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As _
DataGridViewCellStyle) _
Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
MyBase.Font = dataGridViewCellStyle.Font
MyBase.BackColor = dataGridViewCellStyle.BackColor
MyBase.ForeColor = dataGridViewCellStyle.ForeColor
MyBase.BorderStyle = Windows.Forms.BorderStyle.None
End Sub
Public Property EditingControlRowIndex() As Integer _
Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return Me.rowIndexNum
End Get
Set(ByVal value As Integer)
Me.rowIndexNum = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal key As Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
Return True
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() _
As Boolean Implements _
IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView _
Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return Me.dataGridViewControl
End Get
Set(ByVal value As DataGridView)
Me.dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean _
Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return Me.valueIsChanged
End Get
Set(ByVal value As Boolean)
Me.valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor _
Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
Me.valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnTextChanged(e)
End Sub
End Class
Public Class MaskedCell
Inherits DataGridViewTextBoxCell
Public Sub New()
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim column As MaskedColumn = DirectCast(MyBase.DataGridView.Columns(MyBase.ColumnIndex), MaskedColumn)
Me.Mask = column.Mask
Dim ctl As MaskedEditingControl = _
DirectCast(DataGridView.EditingControl, MaskedEditingControl)
ctl.Mask = Me.Mask
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
Return GetType(MaskedEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
Return String.Empty
End Get
End Property
Private m_mask As String
Public Property Mask() As String
Get
Return Me.m_mask
End Get
Set(ByVal value As String)
Me.m_mask = value
End Set
End Property
Public Overrides Function Clone() As Object
Dim cell As MaskedCell = DirectCast(MyBase.Clone(), MaskedCell)
cell.Mask = Me.Mask
Return cell
End Function
End Class
Public Class MaskedColumn
Inherits DataGridViewColumn
Public Property Mask() As String
Get
Return DirectCast(MyBase.CellTemplate, MaskedCell).Mask
End Get
Set(ByVal value As String)
DirectCast(MyBase.CellTemplate, MaskedCell).Mask = value
End Set
End Property
Public Sub New()
MyBase.New(New MaskedCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
If Not (value Is Nothing) AndAlso _
Not value.GetType().IsAssignableFrom(GetType(MaskedCell)) _
Then
Throw New InvalidCastException("Must be a MaskedCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
#End Region
#Region "AutoComplete 列"
Public Class AutoCompletableTextCell
Inherits DataGridViewTextBoxCell
Public Sub New()
Me.m_autoCompleteCustomSource = Nothing
Me.m_autoCompleteMode = Windows.Forms.AutoCompleteMode.None
Me.m_autoCompleteSource = Windows.Forms.AutoCompleteSource.None
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim ctl As DataGridViewTextBoxEditingControl = _
DirectCast(DataGridView.EditingControl, DataGridViewTextBoxEditingControl)
Dim column As AutoCompletableTextColumn = _
DirectCast(Me.OwningColumn, AutoCompletableTextColumn)
Me.AutoCompleteCustomSource = column.AutoCompleteCustomSource
Me.AutoCompleteMode = column.AutoCompleteMode
Me.AutoCompleteSource = column.AutoCompleteSource
ctl.AutoCompleteCustomSource = Me.AutoCompleteCustomSource
ctl.AutoCompleteMode = Me.AutoCompleteMode
ctl.AutoCompleteSource = Me.AutoCompleteSource
End Sub
Private m_autoCompleteCustomSource As AutoCompleteStringCollection
Private m_autoCompleteMode As AutoCompleteMode
Private m_autoCompleteSource As AutoCompleteSource
Public Property AutoCompleteCustomSource() As AutoCompleteStringCollection
Get
Return Me.m_autoCompleteCustomSource
End Get
Set(ByVal value As AutoCompleteStringCollection)
Me.m_autoCompleteCustomSource = value
End Set
End Property
Public Property AutoCompleteMode() As AutoCompleteMode
Get
Return Me.m_autoCompleteMode
End Get
Set(ByVal value As AutoCompleteMode)
Me.m_autoCompleteMode = value
End Set
End Property
Public Property AutoCompleteSource() As AutoCompleteSource
Get
Return Me.m_autoCompleteSource
End Get
Set(ByVal value As AutoCompleteSource)
Me.m_autoCompleteSource = value
End Set
End Property
Private Function GetAutoCompleteCustomSourceClone() As AutoCompleteStringCollection
If Me.AutoCompleteCustomSource Is Nothing Then Return Nothing
Dim enm As IEnumerator = Me.AutoCompleteCustomSource.GetEnumerator()
Dim copyAutoCompleteStringCollection As AutoCompleteStringCollection = New AutoCompleteStringCollection
While enm.MoveNext
copyAutoCompleteStringCollection.Add(Convert.ToString(enm.Current))
End While
Return copyAutoCompleteStringCollection
End Function
Public Overrides Function Clone() As Object
Dim cell As AutoCompletableTextCell = DirectCast(MyBase.Clone(), AutoCompletableTextCell)
cell.AutoCompleteCustomSource = Me.GetAutoCompleteCustomSourceClone()
cell.AutoCompleteMode = Me.AutoCompleteMode
cell.AutoCompleteSource = Me.AutoCompleteSource
Return cell
End Function
End Class
Public Class AutoCompletableTextColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New AutoCompletableTextCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
If Not (value Is Nothing) AndAlso _
Not value.GetType().IsAssignableFrom(GetType(AutoCompletableTextCell)) _
Then
Throw New InvalidCastException("Must be a AutoCompletableTextCell")
End If
MyBase.CellTemplate = value
End Set
End Property
Public Property AutoCompleteCustomSource() As AutoCompleteStringCollection
Get
Return DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteCustomSource
End Get
Set(ByVal value As AutoCompleteStringCollection)
DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteCustomSource = value
End Set
End Property
Public Property AutoCompleteMode() As AutoCompleteMode
Get
Return DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteMode
End Get
Set(ByVal value As AutoCompleteMode)
DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteMode = value
End Set
End Property
Public Property AutoCompleteSource() As AutoCompleteSource
Get
Return DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteSource
End Get
Set(ByVal value As AutoCompleteSource)
DirectCast(MyBase.CellTemplate, AutoCompletableTextCell).AutoCompleteSource = value
End Set
End Property
End Class
#End Region
' TabStop 関連
Public Interface ISupportTabStop
Property TabStop() As Boolean
End Interface
Public Class TabStopTextBoxEditingControl
Inherits DataGridViewTextBoxEditingControl
End Class
Public Class TabStopTextBoxCell
Inherits DataGridViewTextBoxCell
Implements ISupportTabStop
Private m_tabStop As Boolean
Public Property TabStop() As Boolean Implements ISupportTabStop.TabStop
Get
Return Me.m_tabStop
End Get
Set(ByVal value As Boolean)
Me.m_tabStop = value
End Set
End Property
Public Sub New()
Me.m_tabStop = True
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim column As TabStopTextBoxColumn = DirectCast(MyBase.DataGridView.Columns(MyBase.ColumnIndex), TabStopTextBoxColumn)
Me.TabStop = column.TabStop
End Sub
Public Overrides ReadOnly Property EditType() As System.Type
Get
Return GetType(TabStopTextBoxEditingControl)
End Get
End Property
Public Overrides Function Clone() As Object
Dim cell As TabStopTextBoxCell = DirectCast(MyBase.Clone(), TabStopTextBoxCell)
cell.TabStop = Me.TabStop
Return cell
End Function
End Class
Public Class TabStopTextBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New TabStopTextBoxCell())
End Sub
Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As System.Windows.Forms.DataGridViewCell)
If Not (value Is Nothing) AndAlso _
Not value.GetType().IsAssignableFrom(GetType(TabStopTextBoxCell)) _
Then
Throw New InvalidCastException("Must be a TabStopTextBoxCell")
End If
MyBase.CellTemplate = value
End Set
End Property
Public Property TabStop() As Boolean
Get
Return DirectCast(MyBase.CellTemplate, TabStopTextBoxCell).TabStop
End Get
Set(ByVal value As Boolean)
DirectCast(MyBase.CellTemplate, TabStopTextBoxCell).TabStop = value
End Set
End Property
End Class
Public Class TabStopDataGridView
Inherits DataGridView
Public Sub New()
Me.InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer = Nothing
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso Not Me.components Is Nothing Then
Me.components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
End Sub
Private Function GetFirstColumnIndex() As Integer
Dim column As DataGridViewColumn = _
Me.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Dim index As Integer = Convert.ToInt32(IIf(column Is Nothing, -1, column.Index))
Return index
End Function
Private Function GetFirstRowIndex() As Integer
Return Me.Rows.GetFirstRow(DataGridViewElementStates.Visible)
End Function
Private Function GetLastColumnIndex() As Integer
Dim column As DataGridViewColumn = _
Me.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Dim index As Integer = Convert.ToInt32(IIf(column Is Nothing, -1, column.Index))
Return index
End Function
Private Function GetLastRowIndex() As Integer
Return Me.Rows.GetLastRow(DataGridViewElementStates.Visible)
End Function
Private Function GetNextTabPosition(ByVal currentCellAddress As Point) As Point
Dim nextCellAddress As Point = New Point(-1, -1)
Dim nextColumnIndex As Integer = -1
If Me.CurrentCellAddress.X <> -1 Then
Dim column As DataGridViewColumn = Me.Columns.GetNextColumn(Me.Columns(currentCellAddress.X), _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
If Not column Is Nothing Then
nextColumnIndex = column.Index
End If
End If
If nextColumnIndex = -1 Then
nextCellAddress.X = Me.GetFirstColumnIndex()
nextCellAddress.Y = Me.Rows.GetNextRow(currentCellAddress.Y, _
DataGridViewElementStates.Visible)
If nextCellAddress.Y = -1 Then
nextCellAddress.Y = Me.GetFirstRowIndex()
End If
Else
nextCellAddress.X = nextColumnIndex
nextCellAddress.Y = currentCellAddress.Y
End If
Return nextCellAddress
End Function
Private Function CanTabToNextCell() As Boolean
Dim found As Boolean = False
Dim currentCellAddress As Point = Me.CurrentCellAddress
Do While (Not found)
Dim nextCellAddress As Point = Me.GetNextTabPosition(currentCellAddress)
If TypeOf MyBase.Rows(nextCellAddress.Y).Cells(nextCellAddress.X) Is ISupportTabStop Then
Dim tabstopcell As ISupportTabStop = _
DirectCast(Me.Rows(nextCellAddress.Y).Cells(nextCellAddress.X), ISupportTabStop)
If tabstopcell.TabStop Then found = True
Else
found = True
End If
If Not found AndAlso _
nextCellAddress.X <= currentCellAddress.X AndAlso _
nextCellAddress.Y <= currentCellAddress.Y Then
Return False
End If
currentCellAddress = nextCellAddress
Loop
Return True
End Function
Private Function TabToNextCell(ByVal keyData As Keys) As Boolean
If Me.GetFirstColumnIndex() = -1 OrElse Me.GetFirstRowIndex() = -1 Then Return False
If Not Me.CanTabToNextCell() Then Return False
Return Me.TabToCell(keyData)
End Function
Private Function GetPreviousTabPosition(ByVal currentCellAddress As Point) As Point
Dim previousCellAddress As Point = New Point(-1, -1)
Dim previousColumnIndex As Integer = -1
If Me.CurrentCellAddress.X <> -1 Then
Dim column As DataGridViewColumn = Me.Columns.GetPreviousColumn(Me.Columns(currentCellAddress.X), _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
If Not column Is Nothing Then
previousColumnIndex = column.Index
End If
End If
If previousColumnIndex = -1 Then
previousCellAddress.X = Me.GetLastColumnIndex()
previousCellAddress.Y = Me.Rows.GetPreviousRow(currentCellAddress.Y, _
DataGridViewElementStates.Visible)
If previousCellAddress.Y = -1 Then
previousCellAddress.Y = Me.GetLastRowIndex()
End If
Else
previousCellAddress.X = previousColumnIndex
previousCellAddress.Y = currentCellAddress.Y
End If
Return previousCellAddress
End Function
Private Function CanTabToPreviousCell() As Boolean
Dim found As Boolean = False
Dim currentCellAddress As Point = Me.CurrentCellAddress
Do While (Not found)
Dim previousCellAddress As Point = Me.GetPreviousTabPosition(currentCellAddress)
If TypeOf MyBase.Rows(previousCellAddress.Y).Cells(previousCellAddress.X) Is ISupportTabStop Then
Dim tabstopcell As ISupportTabStop = _
DirectCast(Me.Rows(previousCellAddress.Y).Cells(previousCellAddress.X), ISupportTabStop)
If tabstopcell.TabStop Then found = True
Else
found = True
End If
If Not found AndAlso _
previousCellAddress.X >= currentCellAddress.X AndAlso _
previousCellAddress.Y >= currentCellAddress.Y Then
Return False
End If
currentCellAddress = previousCellAddress
Loop
Return True
End Function
Private Function TabToPreviousCell(ByVal keyData As Keys) As Boolean
If Me.GetFirstColumnIndex() = -1 OrElse Me.GetFirstRowIndex() = -1 Then Return False
If Not Me.CanTabToPreviousCell() Then Return False
Return Me.TabToCell(keyData)
End Function
Private Function TabToCell(ByVal keyData As Keys) As Boolean
Dim found As Boolean = False
Dim currentCellAddress As Point = Me.CurrentCellAddress
Do While (Not found)
Dim processed As Boolean = MyBase.ProcessTabKey(keyData)
If Not processed Then Return False
If TypeOf Me.CurrentCell Is ISupportTabStop Then
Dim tabstopcell As ISupportTabStop = DirectCast(Me.CurrentCell, ISupportTabStop)
If tabstopcell.TabStop Then Return True
Else
Return processed
End If
Loop
Return False
End Function
Protected Overrides Function ProcessDataGridViewKey(ByVal e As System.Windows.Forms.KeyEventArgs) As Boolean
Select Case e.KeyData
Case Keys.Tab
Return Me.TabToNextCell(e.KeyData)
Case Keys.Shift Or Keys.Tab
Return Me.TabToPreviousCell(e.KeyData)
End Select
Return MyBase.ProcessDataGridViewKey(e)
End Function
End Class