当多选时,DataGridView KeyDown操作(输入,左,右等)不起作用

时间:2015-06-16 17:42:19

标签: c# winforms datagridview multi-select

我希望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列或更多列。

如果我能提供其他内容,请告诉我。

2 个答案:

答案 0 :(得分:0)

您是否设置了选择模式?

dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;

答案 1 :(得分:0)

GridNavigation方法中,在if (keys == Keys.Enter || keys == Keys.Right)else if (keys == Keys.Left)这两个条件下,此处的有罪方是重复的行:

dataGridView1.Rows[iRow].Cells[i].Selected = true;

出了什么问题?

dataGridView1.MultiSelect == false上述行有效地设置当前单元格时,而不仅仅是Selected属性。即:

  1. CurrentCell = Rows[0].Cells[0]Rows[0].Cells[0].Selected = true
  2. 用户点击 -> 输入
    • Rows[0].Cells[1].Selected = true
    • CurrentCell = Rows[0].Cells[1]
    • Rows[0].Cells[0].Selected = false
  3. 然而,当dataGridView1.MultiSelect == true同一行代码时,设置当前单元格。因此,当前单元格以及左侧或右侧的相邻单元格保持被选中。即:

    1. CurrentCell = Rows[0].Cells[0]Rows[0].Cells[0].Selected = true
    2. 用户点击 -> 输入
      • Rows[0].Cells[1].Selected = true
      • CurrentCell = Rows[0].Cells[0]
      • Rows[0].Cells[0].Selected = true
    3. 用户再次点击 -> 输入
      • 预期成果:Rows[0].Cells[2].Selected = true
      • 实际结果:Rows[0].Cells[1].Selected = true ...再次。
    4. <强>解决方案

      如果您希望它的行为与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;
        }
      }