使用DataGridView CheckBox列模拟datagridview中的单选按钮

时间:2014-04-30 05:38:34

标签: vb.net winforms datagridview

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

我有一个winforms应用,其中包含一个带有三个复选框(DataGridView)列的DataGridViewCheckBoxColumn。我想模仿radiobuttons即。一次只检查一个复选框。单击一个时,我可以关闭网格中的其他复选框,如下所示:

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

我遇到的问题是,如果用户点击已经选中的复选框,它将被取消选中,然后检查三个复选框中的任何一个。我总是希望一个(并且只有一个)复选框一直打勾。

3 个答案:

答案 0 :(得分:2)

使用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

答案 1 :(得分:1)

第一步,编辑三个DataGridView列并将每个列属性ReadOnly设置为true (这将阻止用户更改值)

  1. dclLeaveOnThisList
  2. dclPrintLetter
  3. dclNoLetterNeeded
  4. 和第二,使用下面的代码

    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
    

答案 2 :(得分:1)

您可以结合使用这些DataGridView事件:

  • CellValueChanged
  • CurrentCellDirtyStateChanged
  • CellBeginEdit

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

CurrentCellDirtyStateChanged 事件在单击CheckBox时提交更改。

CellBeginEdit 中的代码阻止用户修改已检查的CheckBox。

这是一个例子:

    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