0

親タブが最初に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

クラス終了

4

1 に答える 1

0

HeaderCell と Column の Clone をオーバーライドすると、問題が解決します

    Public Overrides Function Clone() As Object

        Dim Copy As DGVColumn = DirectCast(MyBase.Clone, DGVColumn)
        Copy._headerCell = DirectCast(_headerCell.Clone, DataGridViewColumnHeaderCell)
        Copy.HeaderCell = Copy._HeaderCell
        Return Copy

    End Function
于 2014-08-07T15:28:10.513 に答える