【问题标题】:DataGridView MouseWheel sendkeys updown issueDataGridView MouseWheel sendkeys updown问题
【发布时间】:2018-10-01 20:20:13
【问题描述】:

我创建了一个子类 datagridview 来覆盖鼠标滚轮事件以捕捉鼠标滚动,然后发送向上或向下键。我创建一个数据表,通过按钮单击绑定为 mydatagridview 的数据源

    private void button1_Click(object sender, EventArgs e)
    {
        DataTable myDataTable = new DataTable();

        int NUM_ROWS = 150;
        int NUM_COLS_TO_CREATE = 10;

        for (int i = 0; i < NUM_COLS_TO_CREATE; i++)
        {
            myDataTable.Columns.Add("x" + i, typeof(string));
        }

        for (int i = 0; i < NUM_ROWS; i++)
        {
            var theRow = myDataTable.NewRow();

            for (int j = 0; j < NUM_COLS_TO_CREATE; j++)
            {
                theRow[j] = "whatever";
            }

            //add the row *after* populating it
            myDataTable.Rows.Add(theRow);
        }

        MyDataGridView1.DataSource = myDataTable;
    }

覆盖鼠标滚轮事件的代码

public partial class MyDataGridView : DataGridView
{
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        if (e.Delta < 0)
            SendKeys.Send("{DOWN}");
        else
            SendKeys.Send("{UP}");
    }
}

如果我们使用鼠标滚轮以 SLOW 的方式滚动每个项目,它工作正常,但如果您使用鼠标滚轮滚动太快,则 datagridview 在某种程度上会变得滞后。

例如从第 1 行到第 5 行,它会从第 1 行跳到第 3 行,然后从第 3 行跳到第 5 行,类似这样,这里又出现了一个奇怪的问题。我在日常生活中经常使用“Navicat”..

所以如果我同时打开我的应用程序和 Navicat。即使我滚动得太快,鼠标滚轮滚动现在在我的应用程序上也变得非常流畅。但是如果我关闭 Navicat,那么滚动就会再次滞后。这是什么原因造成的?如果我不能很好地解释它,我很抱歉,我只想让每个项目的滚动顺畅。有什么建议吗?

【问题讨论】:

    标签: c# performance datagridview scroll mousewheel


    【解决方案1】:

    正如@Bozhidar 提到的,我应该更好地处理 MouseWheel 事件或覆盖它。所以我想出了解决方案,以防万一有人也需要它。

    在 Form_Load 中添加

    MyDataGridView1.MouseWheel += new MouseEventHandler(MyDataGridView1_MouseWheel);
    

    然后把它放在你班级的任何地方

    private void MyDataGridView1_MouseWheel(object sender, MouseEventArgs e)
    {
        HandledMouseEventArgs hme = (HandledMouseEventArgs)e;
        hme.Handled = true;
    
        int rowIndex = MyDataGridView1.CurrentCell.RowIndex;
        int cellIndex = MyDataGridView1.CurrentCell.ColumnIndex;
    
        MyDataGridView1.CurrentCell = MyDataGridView1.Rows[e.Delta < 0 ? Math.Min(rowIndex + 1, MyDataGridView1.RowCount - 1) : Math.Max(rowIndex - 1, 0)].Cells[cellIndex];
    
    }
    

    【讨论】:

      【解决方案2】:

      SendKeys 方法在精确计时方面并不可靠 - 请参阅official documentation。尝试将“SendKeys”应用设置设置为“SendInput”以强制执行新行为。

      但您最好处理 MouseWheel 事件,而不是覆盖它。您需要手动钩住它 - 不知道为什么它没有出现在属性窗口中。鉴于您的DataGridView 被命名为dgv

      private void Form1_Load(object sender, EventArgs e)
      {
          dgv.MouseWheel += Dgv_MouseWheel;
      }
      

      接下来,你考虑过FirstDisplayedScrollingRowIndex吗?只需在事件中适当设置它,并设置Handled 标志,如下所示:

      private void dgv_MouseWheel(object sender, MouseEventArgs e)
      {
          dgv.FirstDisplayedScrollingRowIndex += 3;
          var he = (HandledMouseEventArgs);
          he.Handled = true;
      }
      

      【讨论】:

      • 您好,感谢您的回复。我不能使用 FirstDisplayerScrollingRowIndex,因为我希望选择当前单元格(突出显示)。与按向上或向下按钮的方式相同。
      • 嗯。这是另一个问题。这听起来像“如何以编程方式选择 DataGridView 中的特定单元格。”只需按照您在 answer 中提到的方式选择它即可。
      【解决方案3】:

      这是一种保留滚动视口的默认滚动行为但不更改行选择的方法。

      当在虚拟网格中处理数百万行时,它的执行速度也比内置鼠标滚轮处理程序快得多:

      private void Form1_Load(object sender, EventArgs e)
      {
          DataGridView1.MouseWheel += DataGridView1_MouseWheel;
      }
      
      private void DataGridView1_MouseWheel(object sender, MouseEventArgs e)
      {
          var hme = e as HandledMouseEventArgs;
          hme.Handled = true;
      
          int displayedRowIndex = DataGridView1.FirstDisplayedScrollingRowIndex;
      
          // each "detente" scroll appears to create a delta of 120
          // dividing delta by 120 to get the number of rows scrolled
          // taking the negative of the delta so that it can be added to the displayedRowIndex intuitively as negative is down, positive is up
          var rowDelta = -(e.Delta / 120);
      
          var newDisplayedRowIndex = e.Delta < 0 ? Math.Min(displayedRowIndex + rowDelta, DataGridView1.RowCount - 1) : Math.Max(displayedRowIndex + rowDelta, 0);
      
          DataGridView1.FirstDisplayedScrollingRowIndex = newDisplayedRowIndex;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多