Vb.net 使用DataGridViewCheckBoxColumns模拟datagridview中的单选按钮
请注意:这个问题是关于DataGridView控件中的DataGridViewCheckBoxColumns的,而不是普通的CheckBox控件 我有一个winforms应用程序,它包含一个DataGridView,其中包含三个复选框DataGridViewCheckBoxColumn列。我想模仿单选按钮,即一次只选中一个复选框。单击一个复选框时,我可以关闭网格中的其他复选框,如下所示: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
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也很有用