Reputation: 1061
Friends, I'm working on windows application using C#. I'm using a datagridview to display records. The functionality I need is when I press "Enter" key the focus should go to the next cell(column of same row). If it's the last column in the grid then the focus should go to the first column of the next row. I've already tried using
SendKeys.Send("{Tab}")
in datagridview1_KeyDown and datagridview1_KeyPress event. But focus is moving diagonally down. Please help me to solve this.
Upvotes: 13
Views: 84673
Reputation: 2885
Posting a bit modified version of @Amritpal Singhs' answer.
If you have hidden(Visible=false)
columns as a last column of your grid, then @Amritpal Singhs' solution will throw an error. Below solution takes into account those hidden columns and works without exception:
private void gridDetails_SelectionChanged(object sender, EventArgs e)
{
if (MouseButtons != 0) return;
if (_lastCellEndEdit != null && gridDetails.CurrentCell != null)
{
// if we are currently in the next line of last edit cell
if (gridDetails.CurrentCell.RowIndex == _lastCellEndEdit.RowIndex + 1 &&
gridDetails.CurrentCell.ColumnIndex == _lastCellEndEdit.ColumnIndex)
{
int iColNew;
int iRowNew = 0;
var lastCellEndEditColumn = gridDetails.Columns[_lastCellEndEdit.ColumnIndex];
if (lastCellEndEditColumn.DisplayIndex >= GetVisibleColumnsMaxDisplayIndex())
{
iColNew = GetFirstVisibleColumnIndex();
iRowNew = gridDetails.CurrentCell.RowIndex;
}
else
{
iColNew = GetNextVisibleColumnIndex(lastCellEndEditColumn.DisplayIndex);
iRowNew = _lastCellEndEdit.RowIndex;
}
gridDetails.CurrentCell = gridDetails[iColNew, iRowNew];
}
}
_lastCellEndEdit = null;
}
private DataGridViewCell _lastCellEndEdit;
private void gridDetails_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
_lastCellEndEdit = gridDetails[e.ColumnIndex, e.RowIndex];
}
int GetVisibleColumnsMaxDisplayIndex()
{
int maxDisplayIndex = -1;
foreach (DataGridViewColumn column in gridDetails.Columns)
{
if (column.Visible && column.DisplayIndex > maxDisplayIndex)
{
maxDisplayIndex = column.DisplayIndex ;
}
}
return maxDisplayIndex;
}
int GetFirstVisibleColumnIndex()
{
var firstVisibleColumnDisplayIndex = gridDetails.Columns.Count - 1;
var firstVisibleColumnIndex = 0;
foreach (DataGridViewColumn column in gridDetails.Columns)
{
if (column.Visible && column.DisplayIndex < firstVisibleColumnDisplayIndex)
{
firstVisibleColumnDisplayIndex = column.DisplayIndex;
firstVisibleColumnIndex = column.Index;
}
}
return firstVisibleColumnIndex;
}
int GetNextVisibleColumnIndex(int previousColumnDisplayIndex)
{
var nextVisibleColumnDisplayIndex = gridDetails.Columns.Count;
var nextVisibleColumnIndex = previousColumnDisplayIndex;
foreach (DataGridViewColumn column in gridDetails.Columns)
{
if (column.Visible && column.DisplayIndex > previousColumnDisplayIndex
&& (column.DisplayIndex - previousColumnDisplayIndex) <= (nextVisibleColumnDisplayIndex - previousColumnDisplayIndex))
{
nextVisibleColumnDisplayIndex = column.DisplayIndex;
nextVisibleColumnIndex = column.Index;
}
}
return nextVisibleColumnIndex;
}
Upvotes: 0
Reputation: 2132
Even though the codes I tried moved the focus to next cell, They where effecting the mouse click when the cell was in edit mode. This is what I came up with in the end.
bool _dgv_list_cellEndEdit = false; // class level variable
void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
e.SuppressKeyPress=true;
SendKeys.Send("{Tab}");
}
}
void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
_dgv_list_cellEndEdit=true;
}
void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
_dgv_list_cellEndEdit=false;
}
void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if(_dgv_list_cellEndEdit)
{
_dgv_list_cellEndEdit=false;
SendKeys.Send("{Up}");
SendKeys.Send("{Tab}");
}
}
Upvotes: 0
Reputation: 12884
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
int iColumn = dataGridView1.CurrentCell.ColumnIndex;
int iRow = dataGridView1.CurrentCell.RowIndex;
if (iColumn == dataGridView1.Columncount-1)
{
if (dataGridView1.RowCount > (iRow + 1))
{
dataGridView1.CurrentCell = dataGridView1[1, iRow + 1];
}
else
{
//focus next control
}
}
else
dataGridView1.CurrentCell = dataGridView1[iColumn + 1, iRow];
}
Upvotes: 14
Reputation: 1785
you can use selectionchanged event of the datagridview. In your form
private DataGridViewCell _celWasEndEdit;
private void datagridview_SelectionChanged(object sender, EventArgs e)
{
if (MouseButtons != 0) return;
if (_celWasEndEdit != null && datagridview.CurrentCell != null)
{
// if we are currently in the next line of last edit cell
if (datagridview.CurrentCell.RowIndex == _celWasEndEdit.RowIndex + 1 &&
datagridview.CurrentCell.ColumnIndex == _celWasEndEdit.ColumnIndex)
{
int iColNew;
int iRowNew = 0;
if (_celWasEndEdit.ColumnIndex >= datagridview.ColumnCount - 1)
{
iColNew = 0;
iRowNew = dgvItems.CurrentCell.RowIndex;
}
else
{
iColNew = _celWasEndEdit.ColumnIndex + 1;
iRowNew = _celWasEndEdit.RowIndex;
}
datagridview.CurrentCell = datagridview[iColNew, iRowNew];
}
}
_celWasEndEdit = null;
}
private void datagridview_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
_celWasEndEdit = dgvItems[e.ColumnIndex, e.RowIndex];
}
Upvotes: 6
Reputation: 805
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
int icolumn = dataGridView1.CurrentCell.ColumnIndex;
int irow = dataGridView1.CurrentCell.RowIndex;
if (keyData == Keys.Enter)
{
if (icolumn == dataGridView1.Columns.Count - 1)
{
dataGridView1.Rows.Add();
dataGridView1.CurrentCell = dataGridView1[0, irow + 1];
}
else
{
dataGridView1.CurrentCell = dataGridView1[icolumn + 1, irow];
}
return true;
}
else
return base.ProcessCmdKey(ref msg, keyData);
}
}
Upvotes: 11
Reputation: 698
bool notlastColumn =true; //class level variable--- to check either last column is reached or not
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.ColumnCount - 1 == e.ColumnIndex) //if last column
{
KeyEventArgs forKeyDown = new KeyEventArgs(Keys.Enter);
notlastColumn = false;
dataGridView1_KeyDown(dataGridView1, forKeyDown);
}
else
{
SendKeys.Send("{up}");
SendKeys.Send("{right}");
}
}
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && notlastColumn) //if not last column move to nex
{
SendKeys.Send("{up}");
SendKeys.Send("{right}");
}
else if (e.KeyCode == Keys.Enter)
{
SendKeys.Send("{home}");//go to first column
notlastColumn = true;
}
}
Upvotes: 2