親タブが最初にDGV
表示されるタブではなく、タブコントロールにあります(つまり、TabPage1が表示されたTabPage2のdgv)。
グリッドのデータ ソースはフォームの読み込み時に読み込まれ、割り当てられます。データ バインディングが完了したら、新しい列を追加し、ヘッダー セルのクリックにイベント ハンドラーを割り当てます。これまでのところすべて問題ありません。
しかし、タブを変更してDGV
可視データ バインディングを 2 回目に完全に起動させると、この段階でイベント ハンドラーが失われます。イベントが 2 回目に発生する原因は何ですか?
イベント ハンドラーが失われた原因は何ですか? これを回避する方法はありますか?
ありがとう
編集:
原因は、列が基になる型に戻っているようです。つまり、DataBindingComplete で、DataGridViewTextBoxColumn から継承する列 DGVTextColumn を追加します。2 回目に DataBindingComplete が列を起動すると、継承された型 DGVTextColumn ではなく、DataGridViewTextBoxColumn 型になります。 ?
重要な要素は、バインドされている列、空のフォームを取得してそれにタブ コントロールを追加すること、tabpage2 に a を配置することdatagridview
、tabpage1 に戻ること、フォーム コードの下部にあるコードを貼り付けることです。
Private Sub DataGridView1_DataBindingComplete(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
If Not DataGridView1.Columns.Contains("colBool") Then
Dim col As New DGVColumn
col.Name = "colBool"
col.DataPropertyName = "Checked" 'When this is included the checkbox appears unticked, however commenting this line out means that the checkbox appears ticked upon changing to TabPage2
col.Checked = True
DataGridView1.Columns.Add(col)
End If
End Sub
再現するコード:
Imports System.ComponentModel
Imports System.Windows.Forms.VisualStyles
Public Class Form1
Private list As BindingList(Of iPerson)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
list = New BindingList(Of iPerson)
list.Add(New Person(0, "Steve", "Smith"))
list.Add(New Person(1, "Gomez", "Juan"))
list.Add(New Person(1, "Jones", "Paul"))
DataGridView1.DataSource = list
End Sub
Private Sub DataGridView1_DataBindingComplete(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
If Not DataGridView1.Columns.Contains("colBool") Then
Dim col As New DGVColumn
col.Name = "colBool"
col.DataPropertyName = "Checked"
col.Checked = True
DataGridView1.Columns.Add(col)
End If
End Sub
Private Interface iPerson
ReadOnly Property Forename() As String
ReadOnly Property Surname() As String
ReadOnly Property Checked() As Boolean
End Interface
Private Class Person
Implements iPerson
Private _ID As Integer
Private _Forename As String
Private _Surname As String
Private _checked As Boolean
Public Sub New(ByVal ID As Integer, ByVal Forename As String, ByVal Surname As String)
_ID = ID
_Forename = Forename
_Surname = Surname
_checked = False
End Sub
Public ReadOnly Property Forename() As String Implements iPerson.Forename
Get
Return _Forename
End Get
End Property
Public ReadOnly Property Surname() As String Implements iPerson.Surname
Get
Return _Surname
End Get
End Property
Public ReadOnly Property Checked() As Boolean Implements iPerson.Checked
Get
Return _checked
End Get
End Property
End Class
Private Class DGVHeaderCell
Inherits DataGridViewColumnHeaderCell
Private checkBoxLocation As Point
Private checkBoxSize As Size
Private _checked As Boolean = False
Private _cellLocation As New Point()
Public Event OnCheckBoxClicked()
Public Sub New()
End Sub
Protected Overrides Function GetPreferredSize(ByVal graphics As System.Drawing.Graphics, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal rowIndex As Integer, ByVal constraintSize As System.Drawing.Size) As System.Drawing.Size
Dim calcSize = MyBase.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize)
calcSize.Height += CheckBoxRenderer.GetGlyphSize(graphics, System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal).Height + 3
Return calcSize
End Function
Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, ByVal clipBounds As System.Drawing.Rectangle, ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, ByVal dataGridViewElementState As DataGridViewElementStates, ByVal value As Object, ByVal formattedValue As Object, ByVal errorText As String, ByVal cellStyle As DataGridViewCellStyle, ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, ByVal paintParts As DataGridViewPaintParts)
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, "", "", errorText, cellStyle, advancedBorderStyle, paintParts)
Dim p As New Point()
Dim s As Size = CheckBoxRenderer.GetGlyphSize(graphics, System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal)
p.X = CInt(cellBounds.Location.X + (cellBounds.Width / 2) - (s.Width / 2))
p.Y = cellBounds.Location.Y + cellBounds.Height - s.Height - 3
Dim rect As Rectangle = cellBounds
rect.Height -= CheckBoxRenderer.GetGlyphSize(graphics, System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal).Height
Using txtBrush As New SolidBrush(cellStyle.ForeColor)
Dim format As New StringFormat
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
graphics.DrawString(formattedValue.ToString, cellStyle.Font, txtBrush, rect, format)
End Using
_cellLocation = cellBounds.Location
checkBoxLocation = p
checkBoxSize = s
Dim _cbState As CheckBoxState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
If _checked Then
_cbState = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
End If
CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState)
End Sub
Protected Overrides Sub OnMouseClick(ByVal e As DataGridViewCellMouseEventArgs)
Dim p As New Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y)
If p.X >= checkBoxLocation.X AndAlso p.X <= checkBoxLocation.X + checkBoxSize.Width AndAlso p.Y >= checkBoxLocation.Y AndAlso p.Y <= checkBoxLocation.Y + checkBoxSize.Height Then
_checked = Not _checked
RaiseEvent OnCheckBoxClicked()
Me.DataGridView.InvalidateCell(Me)
End If
MyBase.OnMouseClick(e)
End Sub
Public Property Checked() As Boolean
Get
Return _checked
End Get
Set(ByVal value As Boolean)
_checked = value
End Set
End Property
End Class
Friend Class DGVColumn
Inherits DataGridViewTextBoxColumn
Private _headerCell As DGVHeaderCell
Public Sub New()
_headerCell = New DGVHeaderCell()
AddHandler _headerCell.OnCheckBoxClicked, AddressOf THISHANDLER
Me.HeaderCell = _headerCell
Me.Width = 50
End Sub
Private Sub THISHANDLER()
MsgBox("Clicked")
End Sub
Public Property Checked() As Boolean
Get
Return _headerCell.Checked
End Get
Set(ByVal value As Boolean)
_headerCell.Checked = value
End Set
End Property
End Class
クラス終了