如何以像素为增量滚动DataGridView

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

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

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

嗯,不,你不可能两种方式。 65535像素的大小限制不是人为的,它是操作系统中一个难以解决的限制。 根本原因是WM_VSCROLL消息 。 传递的LPARAM参数的值记录为:

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

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

听起来像一个非常糟糕的问题,当然微软应该在他们的软件中解决这些可怕的限制。 但不,这不是他们的优先列表。 与看似奇怪的限制不同,WaitHandle.WaitAny()无法处理包含超过64个项目的数组。 这是故意的,他们认为做错了,而不是他们。 而且,您是一个用户界面,希望用户必须抓住数千行信息,这不是一个非常实用或友好的界面。 比如谷歌显示数十万次查询点击的方式。

很抱歉,但这个要求不是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),这样您就可以诱使用户认为网格一次只滚动一个像素,而实际上只是一个图像。 我不推荐这种方法。

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

除非您希望应用程序的用户获得RSI或CTS,否则我没有看到如此精确地滚动的重点。

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

我希望这对你有所帮助。