【问题标题】:How can I capture the mouse in a DataGridViewRow, so it only moves within the row如何在 DataGridViewRow 中捕获鼠标,使其仅在行内移动
【发布时间】:2015-06-20 06:37:38
【问题描述】:

我正在编写一个预订应用程序,它利用 DataGridView 将 Y 轴上的可用房间和 X 轴上的可用时间列为列。

我希望用户能够拖动选择一个时间范围,但必须一次限制为一行。

控制网格的突出显示方面,以便在鼠标移动时仅突出显示所需的行或在行边界内捕获鼠标是我想到的选项。欢迎任何帮助实施这些任务,甚至是处理任务的新方法!

我宁愿只使用发生鼠标按下事件的 DataRow 来捕获鼠标,不确定是否必须使用剪切矩形来实现这一点。

提前感谢您的帮助。

【问题讨论】:

  • 不要限制用户实际的鼠标移动,这会让你的用户很困惑。处理拖动时发生的事件,检查行号并只允许选择当前行。
  • 我同意限制用户移动是一件坏事。哪个活动?选择改变?细胞状态改变了吗?以及您如何不允许选择除一行之外的任何行?我的意思是取消选择不需要的单元格很容易,但要真正防止选择一行,请详细说明,因为这正是我所需要的。
  • 应该通过网格设置或您的事件处理程序来防止选择整行。为单元格选择处理哪些事件我建议最初处理所有事件并查看何时触发哪个事件(或阅读其相应的文档),然后应该指导您使用哪些事件来防止跨行选择。跨度>
  • 感谢您回复 Bernd。这是 CellStateChanged 事件,并且运行良好。感谢您朝着正确的方向正确推进,我的大脑刚刚完成,需要一点动力。

标签: c# winforms datagridview mousecapture


【解决方案1】:

这可能是一种更好的编写方式,但它确实有效。

private void dataGridView1_CellStateChanged(object sender, DataGridViewCellStateChangedEventArgs e)
    {
        if (dataGridView1.SelectedCells.Count > 1)
        {
            //Retrieves the first cell selected
            var startRow = dataGridView1.SelectedCells[dataGridView1.SelectedCells.Count - 1].RowIndex;

            foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
            {
                if (cell.RowIndex != startRow)
                {
                    cell.Selected = false;
                }
            }
        }
    }

【讨论】:

  • 作为代码中注释的注释:SelectedCells 列表的顺序不保证与用户选择的顺序一致,因此将最后一个作为第一个选择可以给你随机的错误。 MSDN reference(备注下)
【解决方案2】:

作为对 CellStateChanged 事件代码的改进,可以使用以下代码。

private void dataGridView1_CellStateChanged(object sender, DataGridViewCellStateChangedEventArgs e)
{
  if ((e.StateChanged == DataGridViewElementStates.Selected) && // Only handle it when the State that changed is Selected
      (dataGridView1.SelectedCells.Count > 1))
  {
    // A LINQ query on the SelectedCells that does the same as the for-loop (might be easier to read, but harder to debug)
    // Use either this or the for-loop, not both
    if (dataGridView1.SelectedCells.Cast<DataGridViewCell>().Where(cell => cell.RowIndex != e.Cell.RowIndex).Count() > 0)
    {
      e.Cell.Selected = false;
    }

    /*
    foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
    {
      if (cell.RowIndex != e.Cell.RowIndex)
      {
        e.Cell.Selected = false;
        break;  // stop the loop as soon as we found one
      }
    }
    */
  }
}

这个for循环的不同之处在于使用e.Cell作为RowIndex的参考点,因为e.Cell是用户选择的单元格,将e.Cell.Selected设置为false而不是cell.Selected 最后是 for 循环中的 break;,因为在第一个 RowIndex 不匹配之后,我们可以停止检查。

【讨论】:

    猜你喜欢
    • 2013-11-06
    • 2021-01-13
    • 2023-03-19
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    相关资源
    最近更新 更多