Reputation: 1163
By default, a DataGridView is set to EditOnKeystrokeOrF2
edit mode. This means two or three clicks (spaced further apart than the user's double click interval) are required to change the value of a combobox in this view. As this is rather strange for a UI object, you would tend to think the control doesn't work.
Fortunately, you can change the selection mode to EditOnEnter
. This will immediately select a cell when clicking on it, not first select the row, reducing the amount of clicks by 1. However, DataGridViews are implemented somewhat strangely. There is a '-1th' cell that is not manually selectable in each row.
When this '-1th' cell is selected, in the normal selection mode the row is selected, but in the "EditOnEnter" mode the 1st cell in the row is selected instead. If the DataGridView is set to enable row deletion using the "Del" key, then using EditOnEnter makes it impossible to use this functionality.
How do I get both to work? I.e.: I don't have a view where the user can have click up to 6 times (users tend to click more rapidly when they have to do so a lot of times) to open a box, while at the same time allowing row selection using the special -1th column?
Upvotes: 1
Views: 254
Reputation: 1163
One would need to programmatically toggle between both edit modes when any cell in the row is clicked. However, the CellClick
event fires too late: after the row is already selected. Naively just toggling the EditMode
would mean that the first click on the row selection box doesn't work, while the second would, which would appear as buggy behaviour.
The trick is to do much more manually. The following event handler, when attached to the CellClick
event, will resolve almost all issues.
Private Sub CellSelect(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles myDataGridView.CellClick
Dim dgv As DataGridView = CType(sender, DataGridView)
If dgv.Rows.Count = 0 Then
Return
End If
Dim rowToSelect As Integer = e.RowIndex
Dim columnToSelect As Integer = e.ColumnIndex
If e.RowIndex = -1 Then
rowToSelect = 0
End If
If rowToSelect >= dgv.Rows.Count Then
rowToSelect = 0
End If
If columnToSelect = -1 Then
dgv.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect
dgv.CurrentCell = Nothing
dgv.Rows(rowToSelect).Selected = True
Else
If columnToSelect >= dgv.Rows(rowToSelect).Cells.Count Then
columnToSelect = 0
End If
dgv.EditMode = DataGridViewEditMode.EditOnEnter
dgv.SelectionMode = DataGridViewSelectionMode.CellSelect
dgv.Rows(rowToSelect).Cells(columnToSelect).Selected = True
End If
End Sub
It works by unsetting the selected cell, then setting the selected row programmatically. As the EditMode was changed beforehand, it will select the entire row, not just the first cell, even the first time that the row-selection box is clicked.
There are also a whole bunch of edge cases where a user that clicks quickly enough can create click events on cells that do not exist. So we assume those clicks are on the cell [0,0] so at least our application won't blow up.
This isn't a perfect solution (yet). With this solution: A small graphical glitch remains; for about one frame the DataGridView will flicker between edit modes, very briefly appearing as though the row is selected.
Upvotes: 1