【问题标题】:How to scroll DataGridView in pixel increments如何以像素增量滚动 DataGridView
【发布时间】:2015-05-21 13:08:14
【问题描述】:

我最初的方法是将我的 DataGridView 包含在面板内,将其高度设置在面板边界之外,然后更改控制面板的滚动条位置。但是,我刚刚发现我的 DataGridView 中的行数将达到 2000,这迫使我将 DataGridView 的大小至少调整为:

65 像素(行高)x 2,000 = 130,000 像素。

我的 64 位计算机上允许的 DataGridView 控件的最大大小为 65,535。任何人都可以想到解决这个问题的方法吗?

【问题讨论】:

  • 我不会推荐它,但第一件事,除了不将它们全部放在 DGV 中的第一个位置 ;-) 之外,是更改视口内和视口周围除一些之外的所有行的大小.当它们的高度为 0 时,DGV 可能会小很多。听起来很疯狂,也许是,-)
  • @Anthony 为此目的使用 DataGridView 没有任何问题。它为我提供了将数据制成表格、绑定数据和格式化外观的便利,它只是不能做我需要的一件事。
  • 我并不是说不使用 DataGridView,我是说将它的大小设置为巨大的并将其放在另一个可滚动控件中,这样您就可以为巨型 DataGridView 进行像素级滚动是在问问题。
  • 滚动 65 次以进入新行,你一定是在开玩笑!唯一需要此功能的客户是宣传 RSI 的保险公司。
  • @JeremyThompson 这种需要的原因是我正在 DataGridView 上实现需要像素滚动的轻弹。

标签: c# winforms scroll datagridview panel


【解决方案1】:

嗯,不,你不能同时拥有它。 65535 像素的大小限制不是人为的,它是操作系统中根深蒂固的限制。根本原因是WM_VSCROLL message。传递的 LPARAM 参数的值记录为:

如果 LOWORD 是 SB_THUMBPOSITION 或 SB_THUMBTRACK,HIWORD 指定滚动框的当前位置

HIWORD 是值的高 16 位,LOWORD 是低 16 位。只能提供 0 .. Pow(2, 16)-1 = 0..65535 的范围。这个限制在其他地方是可见的,如果你用超过(65535 + 可见)项填充 ListBox,它的行为会很糟糕。你不能再滚动到底部了。

听起来像是一个非常糟糕的问题,微软当然应该在他们的软件中解决这些可怕的限制。但是不,这不在他们的优先级列表之上。与 WaitHandle.WaitAny() 无法处理包含超过 64 个项目的数组这一看似奇怪的限制不同。这是故意的,他们认为做错了,而不是他们。你是,一个期望用户必须通过数千行信息的用户界面不是一个非常有用或友好的界面。例如,从 Google 显示数十万条查询命中的方式中获取线索。

【讨论】:

    【解决方案2】:

    也许您可以将行高设置为 1 像素,这样所有行在加载时都变为 1 像素高。然后假设您知道在您的 DataGridView 的最大高度中可以看到多少行您是否可以确保选择了 1 行并将其放置在其中心。然后使用循环,您可以将所选行的高度和所选行上方和下方的x 行设置为 65 像素。并在所选行发生更改时(当用户使用箭头键等)将所选行滚动到中心并再次调整行大小。对于这种情况,这是我能想到的唯一方法。

    希望对你有所帮助。

    【讨论】:

      【解决方案3】:

      很抱歉,这个要求不是 DataGridView 的工作方式。你不 实际上直接与滚动条交互。

      以这段代码为例,您唯一可以控制的属性是FirstDisplayedScrollingRowIndex

      您不能将 DataGridView 行作为分数滚动(例如,半行滚动或...根据您的需要将更精细的粒度降至像素级别。)

      private void button1_Click(object sender, EventArgs e)
      {
          var dt = new DataTable();
          dt.Columns.Add("test");
      
          var rnd = new Random();
          for (int i = 0; i < 10000; i++)
          {
              var dr = dt.NewRow();
              dr[0] = rnd.Next().ToString();
              dt.Rows.Add(dr);
          }
          dataGridView1.DataSource = dt;
      }
      
      int i = 0;
      int lastTopRow = 0;
      var isRecursive = false;
      private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
      {
          if (isRecursive) return;
          //Honor each 20th scroll for "*attempted gradual*" scrolling
          if (i % 20 == 0)
          {
              lastTopRow++;
          }
      
          isRecursive = true;
          dataGridView1.FirstDisplayedScrollingRowIndex = lastTopRow;
          isRecursive = false;
      
          //Boundary check
          if (i > int.MaxValue) i = 0;
          i++;
      }
      

      您可能需要借助屏幕截图(即使用 Blips),以便您可以 诱使用户认为网格一次滚动一个像素 当它真的只是一个图像。我不会推荐这种方法。

      另一种方法是使用像 Panel 或 GroupBox 这样的 ViewPort 并更改 GridView 的顶部位置。

      除非您希望您的应用程序的用户获得 RSI 或 CTS,否则我看不出如此精确地滚动的意义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-09
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 2014-08-10
        相关资源
        最近更新 更多