Vb.net 使用DataGridViewCheckBoxColumns模拟datagridview中的单选按钮

Vb.net 使用DataGridViewCheckBoxColumns模拟datagridview中的单选按钮,vb.net,winforms,datagridview,Vb.net,Winforms,Datagridview,请注意:这个问题是关于DataGridView控件中的DataGridViewCheckBoxColumns的,而不是普通的CheckBox控件 我有一个winforms应用程序,它包含一个DataGridView,其中包含三个复选框DataGridViewCheckBoxColumn列。我想模仿单选按钮,即一次只选中一个复选框。单击一个复选框时,我可以关闭网格中的其他复选框,如下所示: Private Sub dgvNormalReports_CellClick(sender As Objec

请注意:这个问题是关于DataGridView控件中的DataGridViewCheckBoxColumns的,而不是普通的CheckBox控件

我有一个winforms应用程序,它包含一个DataGridView,其中包含三个复选框DataGridViewCheckBoxColumn列。我想模仿单选按钮,即一次只选中一个复选框。单击一个复选框时,我可以关闭网格中的其他复选框,如下所示:

Private Sub dgvNormalReports_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvNormalReports.CellClick
  If mblnSuppressUI Then Exit Sub
  mblnSuppressUI = True
  If e.ColumnIndex >= 0 And e.ColumnIndex <= dgvNormalReports.ColumnCount - 1 And e.RowIndex >= 0 And e.RowIndex <= dgvNormalReports.Rows.Count - 1 Then
    Select Case dgvNormalReports.Columns(e.ColumnIndex).Name
      Case "dclLeaveOnThisList", "dclPrintLetter", "dclNoLetterNeeded" 'mimic radiobutton - turn off other checkboxes
        dgvNormalReports.Rows(e.RowIndex).Cells("dclLeaveOnThisList").Value = False
        dgvNormalReports.Rows(e.RowIndex).Cells("dclPrintLetter").Value = False
        dgvNormalReports.Rows(e.RowIndex).Cells("dclNoLetterNeeded").Value = False
        'N.B. current cell's checked status is changed AFTER this event
      Case Else
        'ignore
    End Select
  End If
  mblnSuppressUI = False
End Sub
我遇到的问题是,如果用户单击已选中的复选框,它将变为未选中,然后三个复选框中没有一个被选中。我始终希望选中一个且仅选中一个复选框。

第一步,编辑三个DataGridView列,并将每个列的属性设置为只读。这将防止用户更改值

DCLleAveonthilist dclPrintLetter 需要DCLnoletter 第二,使用下面的代码

Private Sub dgvNormalReports_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvNormalReports.CellClick
  If mblnSuppressUI Then Exit Sub
  mblnSuppressUI = True
  If e.ColumnIndex >= 0 And e.ColumnIndex <= dgvNormalReports.ColumnCount - 1 And e.RowIndex >= 0 And e.RowIndex <= dgvNormalReports.Rows.Count - 1 Then

    Dim tmpColName As String = dgvNormalReports.Columns(e.ColumnIndex).Name
    With dgvNormalReports.Rows(e.RowIndex)
        Select Case tmpColName 
        Case "dclLeaveOnThisList", "dclPrintLetter", "dclNoLetterNeeded" 'mimic radiobutton - turn off other checkboxes
                'Unchecked all checkboxes besides the selected one
                If tmpColName <> "dclLeaveOnThisList" Then .Cells("dclLeaveOnThisList").Value = False
                If tmpColName <> "dclPrintLetter" Then .Cells("dclPrintLetter").Value = False
                If tmpColName <> "dclNoLetterNeeded" Then .Cells("dclNoLetterNeeded").Value = False

             'Ensures that the selected cell is checked
             .Cells(e.ColumnIndex).Value = True

        End Select

    End With

  End If
  mblnSuppressUI = False
End Sub
第一步,编辑三个DataGridView列并将每个列属性ReadOnly设置为true,这将防止用户更改值

DCLleAveonthilist dclPrintLetter 需要DCLnoletter 第二,使用下面的代码

Private Sub dgvNormalReports_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvNormalReports.CellClick
  If mblnSuppressUI Then Exit Sub
  mblnSuppressUI = True
  If e.ColumnIndex >= 0 And e.ColumnIndex <= dgvNormalReports.ColumnCount - 1 And e.RowIndex >= 0 And e.RowIndex <= dgvNormalReports.Rows.Count - 1 Then

    Dim tmpColName As String = dgvNormalReports.Columns(e.ColumnIndex).Name
    With dgvNormalReports.Rows(e.RowIndex)
        Select Case tmpColName 
        Case "dclLeaveOnThisList", "dclPrintLetter", "dclNoLetterNeeded" 'mimic radiobutton - turn off other checkboxes
                'Unchecked all checkboxes besides the selected one
                If tmpColName <> "dclLeaveOnThisList" Then .Cells("dclLeaveOnThisList").Value = False
                If tmpColName <> "dclPrintLetter" Then .Cells("dclPrintLetter").Value = False
                If tmpColName <> "dclNoLetterNeeded" Then .Cells("dclNoLetterNeeded").Value = False

             'Ensures that the selected cell is checked
             .Cells(e.ColumnIndex).Value = True

        End Select

    End With

  End If
  mblnSuppressUI = False
End Sub

您可以使用以下DataGridView事件的组合:

CellValueChanged CurrentCellDirtyStateChanged CellBeginEdit 您可以使用CellValueChanged而不是CellClick,因为单击单元格的任何部分(包括边框和填充)时会发生CellClick事件

CurrentCellDirtyStateChanged事件单击复选框时提交更改

CellBeginEdit中的代码阻止用户修改选中的复选框

这是一个例子:

    Private Sub DataGridView1_CellValueChanged(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged

        With Me.DataGridView1

            .CurrentCell.Value = True

            If .Columns(e.ColumnIndex).Name = "dgvchkOptionA" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
            ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionB" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
            ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionC" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
            End If

        End With

    End Sub

    Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged

        If Me.DataGridView1.IsCurrentCellDirty Then
            DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
        End If

    End Sub

    Private Sub DataGridView1_CellBeginEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.CellBeginEdit

        With Me.DataGridView1
            If .CurrentCell Is .Rows(e.RowIndex).Cells(e.ColumnIndex) And _
                .CurrentCell.Value Then e.Cancel = True
        End With

    End Sub

您可以使用以下DataGridView事件的组合:

CellValueChanged CurrentCellDirtyStateChanged CellBeginEdit 您可以使用CellValueChanged而不是CellClick,因为单击单元格的任何部分(包括边框和填充)时会发生CellClick事件

CurrentCellDirtyStateChanged事件单击复选框时提交更改

CellBeginEdit中的代码阻止用户修改选中的复选框

这是一个例子:

    Private Sub DataGridView1_CellValueChanged(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged

        With Me.DataGridView1

            .CurrentCell.Value = True

            If .Columns(e.ColumnIndex).Name = "dgvchkOptionA" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
            ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionB" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
            ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionC" Then
                .Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
                .Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
            End If

        End With

    End Sub

    Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged

        If Me.DataGridView1.IsCurrentCellDirty Then
            DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
        End If

    End Sub

    Private Sub DataGridView1_CellBeginEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.CellBeginEdit

        With Me.DataGridView1
            If .CurrentCell Is .Rows(e.RowIndex).Cells(e.ColumnIndex) And _
                .CurrentCell.Value Then e.Cancel = True
        End With

    End Sub
使用CurrentCellDirtyStateChanged事件处理程序

Private Sub dgvNormalReports_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles dgvNormalReports.CurrentCellDirtyStateChanged
    If Me.dgvNormalReports.IsCurrentCellDirty = True Then
        If Me.dgvNormalReports.CurrentCell.OwningColumn.GetType() = GetType(DataGridViewCheckBoxColumn) Then
            If Me.dgvNormalReports.CurrentCell.Value = False Then
                'Update only if changed from false to true
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclLeaveOnThisList") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclLeaveOnThisList").Value = False
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclPrintLetter") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclPrintLetter").Value = False
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclNoLetterNeeded") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclNoLetterNeeded").Value = False

                Me.dgvNormalReports.CommitEdit(DataGridViewDataErrorContexts.Commit)
            Else
                'Prevent changes
                Me.dgvNormalReports.CancelEdit()
            End If
        End If
    End If
End Sub
如果在datagridview中有预定义的列,则最好使用VisualStudio生成的列对象:

Me.dclLeaveOnThisList.Name
Me.dclPrintLetter.Name
Me.dclNoLetterNeeded.Name
使用CurrentCellDirtyStateChanged事件处理程序

Private Sub dgvNormalReports_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles dgvNormalReports.CurrentCellDirtyStateChanged
    If Me.dgvNormalReports.IsCurrentCellDirty = True Then
        If Me.dgvNormalReports.CurrentCell.OwningColumn.GetType() = GetType(DataGridViewCheckBoxColumn) Then
            If Me.dgvNormalReports.CurrentCell.Value = False Then
                'Update only if changed from false to true
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclLeaveOnThisList") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclLeaveOnThisList").Value = False
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclPrintLetter") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclPrintLetter").Value = False
                If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclNoLetterNeeded") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclNoLetterNeeded").Value = False

                Me.dgvNormalReports.CommitEdit(DataGridViewDataErrorContexts.Commit)
            Else
                'Prevent changes
                Me.dgvNormalReports.CancelEdit()
            End If
        End If
    End If
End Sub
如果在datagridview中有预定义的列,则最好使用VisualStudio生成的列对象:

Me.dclLeaveOnThisList.Name
Me.dclPrintLetter.Name
Me.dclNoLetterNeeded.Name

使用CurrentCellDirtyState的好主意就像你做的一样!恭维!ps:我编辑了你的答案,因为你在一行代码中使用了dgvTest1。我的编辑仍然不可见,但我现在注意到rowindx是无用的。更新了答案,从此再也找不到dgvTest1。使用CurrentCellDirtyState的好主意改变了,就像你做的那样!恭维!ps:我编辑了你的答案,因为你在一行代码中使用了dgvTest1。我的编辑仍然不可见,但我现在注意到rowindx是无用的。更新了答案,从那里再也找不到dgvTest1。我接受这个答案,因为它满足了我的需要,而且是最简单的。感谢所有回答的人!如果要更新格式,dgvNormalReports.InvalidateRowe.RowIndex也很有用。我接受这个答案,因为它满足了我的需要,而且是最简单的。感谢所有回答的人!如果要更新格式,dgvNormalReports.InvalidateRowe.RowIndex也很有用