I want to make the DataGridView
more handy while manipulating the KeyDown
event, like the KeyEnter
for moving one cell to the right, or using left, down or up. I have some special use cases where I want to check first the cell and depending on that I can discard this event for example or point it to an another cell. This is working fine until I set the "multiselect" feature to true. Then the complete process of leaving focus and set the right focus, per cell is not working fine anymore. Please find some sample code below:
private bool GridNavigation(Keys keys)
{
if (dataGridView1.CurrentRow == null)
{
return true;
}
int iColumn = dataGridView1.CurrentCell.ColumnIndex;
int iRow = dataGridView1.CurrentCell.RowIndex;
if (keys == Keys.Enter || keys == Keys.Right)
{
for (int i = iColumn + 1; i <= dataGridView1.Columns.Count - 4; i++)
{
if (!dataGridView1.Rows[iRow].Cells[i].ReadOnly)
{
dataGridView1.Rows[iRow].Cells[i].Selected = true;
break;
}
if (i == dataGridView1.Columns.Count - 4 && dataGridView1.Rows.Count - 1 != iRow)
{
if (((IDictionary<int, int>)dataGridView1.CurrentRow.Tag).SingleOrDefault(p => p.Key == (int)clsDefinitions.ZeilenIndikator.Typ).Value == (int)clsDefinitions.ZeilenTyp.PassLängeAusgangswert)
dataGridView1.CurrentCell = dataGridView1[0, iRow + 2];
else
dataGridView1.CurrentCell = dataGridView1[0, iRow + 1];
return true;
}
}
return true;
}
else if (keys == Keys.Left)
{
for (int i = iColumn - 1; i >= 0; i--)
{
if (!dataGridView1.Rows[iRow].Cells[i].ReadOnly)
{
dataGridView1.Rows[iRow].Cells[i].Selected = true;
break;
}
}
return true;
}
else
return false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter || keyData == Keys.Right || keyData == Keys.Left)
{
return GridNavigation(keyData);
}
return base.ProcessCmdKey(ref msg, keyData);
}
So what can be done here. You can easily reproduce by open a new Project and just put a DataGridView
in the form and add for example 10 columns or more.
If there's something else I can provide, please let me know.
In your
GridNavigation
method, under both conditions,if (keys == Keys.Enter || keys == Keys.Right)
andelse if (keys == Keys.Left)
, the guilty party here is the recurring line:What went wrong?
When
dataGridView1.MultiSelect == false
the above line effectively sets the current cell, not just theSelected
property. I.E:CurrentCell = Rows[0].Cells[0]
,Rows[0].Cells[0].Selected = true
->
or EnterRows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[1]
Rows[0].Cells[0].Selected = false
However, when
dataGridView1.MultiSelect == true
the same line of code does not set the current cell. So the current cell remains selected as well as the adjoining cell to the left or right respectively. I.E:CurrentCell = Rows[0].Cells[0]
,Rows[0].Cells[0].Selected = true
->
or EnterRows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[0]
Rows[0].Cells[0].Selected = true
->
or EnterRows[0].Cells[2].Selected = true
.Rows[0].Cells[1].Selected = true
...again.Solution
If you want it to behave the same as
MultiSelect = false
and only have one selected cell when you navigate left or right, just replace the guilty lines of code with:If you want to retain the previously selected cells, replace the guilty lines of code with: