DataGridView KeyDown 操作(输入、左、右等)在多选时不起作用
DataGridView KeyDown manipulation (enter, left, right, etc.) not working when multiselect
我想让 DataGridView
在操作 KeyDown
事件时更加方便,例如 KeyEnter
用于向右移动一个单元格,或者使用向左、向下或向上。我有一些特殊的用例,我想首先检查单元格,然后根据它我可以丢弃此事件或将其指向另一个单元格。在我将 "multiselect" 功能设置为 true 之前,它工作正常。然后离开焦点和设置正确焦点的完整过程,每个单元格不再正常工作。请在下面找到一些示例代码:
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);
}
那么这里可以做什么。您可以通过打开一个新项目轻松重现,只需在表单中输入 DataGridView
并添加例如 10 列或更多列。
如果我还有什么可以提供的,请告诉我。
你设置选择模式了吗?
dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
在您的 GridNavigation
方法中,在 if (keys == Keys.Enter || keys == Keys.Right)
和 else if (keys == Keys.Left)
两种情况下,这里的有罪方是重复行:
dataGridView1.Rows[iRow].Cells[i].Selected = true;
哪里出了问题?
当 dataGridView1.MultiSelect == false
时,上面的行有效地设置了当前单元格,而不仅仅是 Selected
属性。即:
CurrentCell = Rows[0].Cells[0]
、Rows[0].Cells[0].Selected = true
- 用户点击
->
或输入
Rows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[1]
Rows[0].Cells[0].Selected = false
但是,当 dataGridView1.MultiSelect == true
同一行代码 未 设置当前单元格时。因此,当前单元格以及左侧或右侧的相邻单元格分别保持选中状态。即:
CurrentCell = Rows[0].Cells[0]
、Rows[0].Cells[0].Selected = true
- 用户点击
->
或输入
Rows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[0]
Rows[0].Cells[0].Selected = true
- 用户再次点击
->
或输入
- 预期结果:
Rows[0].Cells[2].Selected = true
.
- 实际结果:
Rows[0].Cells[1].Selected = true
...再次。
解决方案
如果您希望它的行为与 MultiSelect = false
相同,并且当您向左或向右导航时只有 一个 选定的单元格,只需将有罪的代码行替换为:
dataGridView1.CurrentCell = dataGridView.Rows[iRow].Cells[i];
如果要保留之前选择的单元格,请将有问题的代码行替换为:
DataGridViewSelectedCellCollection cells = dataGridView1.SelectedCells;
dataGridView1.CurrentCell = dataGridView1.Rows[iRow].Cells[i];
if (dataGridView1.MultiSelect)
{
foreach (DataGridViewCell cell in cells)
{
cell.Selected = true;
}
}
我想让 DataGridView
在操作 KeyDown
事件时更加方便,例如 KeyEnter
用于向右移动一个单元格,或者使用向左、向下或向上。我有一些特殊的用例,我想首先检查单元格,然后根据它我可以丢弃此事件或将其指向另一个单元格。在我将 "multiselect" 功能设置为 true 之前,它工作正常。然后离开焦点和设置正确焦点的完整过程,每个单元格不再正常工作。请在下面找到一些示例代码:
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);
}
那么这里可以做什么。您可以通过打开一个新项目轻松重现,只需在表单中输入 DataGridView
并添加例如 10 列或更多列。
如果我还有什么可以提供的,请告诉我。
你设置选择模式了吗?
dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
在您的 GridNavigation
方法中,在 if (keys == Keys.Enter || keys == Keys.Right)
和 else if (keys == Keys.Left)
两种情况下,这里的有罪方是重复行:
dataGridView1.Rows[iRow].Cells[i].Selected = true;
哪里出了问题?
当 dataGridView1.MultiSelect == false
时,上面的行有效地设置了当前单元格,而不仅仅是 Selected
属性。即:
CurrentCell = Rows[0].Cells[0]
、Rows[0].Cells[0].Selected = true
- 用户点击
->
或输入Rows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[1]
Rows[0].Cells[0].Selected = false
但是,当 dataGridView1.MultiSelect == true
同一行代码 未 设置当前单元格时。因此,当前单元格以及左侧或右侧的相邻单元格分别保持选中状态。即:
CurrentCell = Rows[0].Cells[0]
、Rows[0].Cells[0].Selected = true
- 用户点击
->
或输入Rows[0].Cells[1].Selected = true
CurrentCell = Rows[0].Cells[0]
Rows[0].Cells[0].Selected = true
- 用户再次点击
->
或输入- 预期结果:
Rows[0].Cells[2].Selected = true
. - 实际结果:
Rows[0].Cells[1].Selected = true
...再次。
- 预期结果:
解决方案
如果您希望它的行为与 MultiSelect = false
相同,并且当您向左或向右导航时只有 一个 选定的单元格,只需将有罪的代码行替换为:
dataGridView1.CurrentCell = dataGridView.Rows[iRow].Cells[i];
如果要保留之前选择的单元格,请将有问题的代码行替换为:
DataGridViewSelectedCellCollection cells = dataGridView1.SelectedCells;
dataGridView1.CurrentCell = dataGridView1.Rows[iRow].Cells[i];
if (dataGridView1.MultiSelect)
{
foreach (DataGridViewCell cell in cells)
{
cell.Selected = true;
}
}