Can anyone show me some code of how I could bypass read only cells in DatagridView when pressing TAB key?
Overriding the SelectionChanged event is the right approach. The property CurrentCell can be used to set the current cell. You want something like this:
private void dataGridView_SelectionChanged(object sender, EventArgs e)
{
DataGridViewCell currentCell = dataGridView.CurrentCell;
if (currentCell != null)
{
int nextRow = currentCell.RowIndex;
int nextCol = currentCell.ColumnIndex + 1;
if (nextCol > dataGridView.ColumnCount)
{
nextCol = 0;
nextRow++;
}
if (nextRow > dataGridView.RowCount)
{
nextRow = 0;
}
DataGridViewCell nextCell = dataGridView.Rows[nextRow].Cells[nextCol];
if (nextCell != null && nextCell.Visible)
{
dataGridView.CurrentCell = nextCell;
}
}
}
You'll need to add a test for the current cell being read only and loop while the next cell is invisible or read only. You'll also need to check to make sure that you don't loop for ever if all cells are read only.
You'll have to cope with the case where the display index is different to the base index too.
EDIT:
To get this behaviour just when pressing Tab you'll need to add a KeyDown handler:
private void AlbumChecker_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
SelectNextEditableCell(DataGridView dataGridView);
}
}
and put the first code in this new method.
You might want to check that the DataGridView has focus too.
Inherit DataGridView and override ProcessDialogKey (for key pressed while editing) and ProcessDataGridViewKey (for key pressed while not editing). When Tab was pressed, set CurrentCell to the next non-readonly cell.
Optionally override WndProc to filter mouse clicks on readonly cells. (See DataGridView.GetColumnDisplayRectangle to find which column was clicked).
Good source to start from here.
When the cell is in edit mode, and you want to listen to keystroke events, you might try handling the DataGridView's EditingControlShowing event...
Private Sub myDvGrid_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles myDvGrid.EditingControlShowing
Dim c As DataGridViewTextBoxEditingControl = DirectCast(e.Control, DataGridViewTextBoxEditingControl)
RemoveHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown
RemoveHandler c.TextChanged, AddressOf edtctrlOn_TextChanged
AddHandler c.TextChanged, AddressOf edtctrlOn_TextChanged
AddHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown
End Sub
Then, in the edtctrlOn_PreviewKeyDown event, you can bubble the arguments over to the original datagrid's PreviewKeyDown event handler.
I did an example Inheriting DataGridView class. The example works for TAB and ENTER keys so the user can quickly insert data, but can still use the mouse or the up, down, right, left keys to select the cells and copy them to an excel. It works simulating several TABs until the Grid gets to a non ReadOnly Cell. Hope it’s use full.
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms;
namespace System.Windows.Forms { class MyDataGridView : DataGridView { protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Enter || keyData == Keys.Tab) { MyProcessTabKey(Keys.Tab); return true; } return base.ProcessDialogKey(keyData); }
protected override bool ProcessDataGridViewKey(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)
{
MyProcessTabKey(Keys.Tab);
return true;
}
return base.ProcessDataGridViewKey(e);
}
protected bool MyProcessTabKey(Keys keyData)
{
bool retValue = base.ProcessTabKey(Keys.Tab);
while (this.CurrentCell.ReadOnly)
{
retValue = base.ProcessTabKey(Keys.Tab);
}
return retValue;
}
} }