如何以像素增量滚动 DataGridView
How to scroll DataGridView in pixel increments
我最初的方法是将我的 DataGridView 包含在一个面板内,将其高度设置在面板边界之外,然后更改控制面板的滚动条位置。但是,我刚刚发现我的 DataGridView 中的行数将达到 2000,这迫使我至少将 DataGridView 的大小调整为:
65px (row height) x 2,000 = 130,000px.
我的 64 位机器上 DataGridView 控件允许的最大大小是 65,535。任何人都可以想办法解决这个问题?
也许您可以将行高设置为大约 1 个像素,这样所有行在所有行加载时都变为 1 个像素高。然后假设您知道在 DataGridView 的最大高度中可以看到多少行你有你可以确保选择 1 行并将其放置在它的中心。然后通过循环,您可以将所选行的高度和所选行上方和下方的 x
行的高度设置为 65 像素。并在所选行发生变化时(当用户使用箭头键等时)将所选行滚动到中心并再次调整行的大小。对于这种情况,这是我能想到的唯一方法。
希望对你有所帮助
Sorry to say but this requirement is not the way a DataGridView works. You don't
actually interact directly with the scrollbar.
以这段代码为例,您唯一可以控制的 属性 是 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 的顶部位置。
Unless you want users of your application getting RSI or CTS I dont see the point in scrolling so precisely.
嗯,不,不能两全其美。 65535 像素的大小限制不是人为的,它是操作系统中的硬限制。根本原因是WM_VSCROLL message。传递的 LPARAM 参数的值记录为:
The HIWORD specifies the current position of the scroll box if the LOWORD is SB_THUMBPOSITION or SB_THUMBTRACK
HIWORD为值的高16位,LOWORD为低16位。其中只能提供 0 .. Pow(2, 16)-1 = 0..65535 的范围。此限制在其他地方可见,如果您用超过(65535 + 可见)项填充列表框,它会出现不良行为。您不能再滚动到底部了。
听起来像是一个非常糟糕的问题,微软当然应该在他们的软件中修复这些可怕的限制。但是不,这不在他们的优先列表中。与 WaitHandle.WaitAny() 无法处理包含超过 64 个项目的数组这一看似奇怪的限制没有什么不同。这是故意的,他们认为你做错了,不是他们。而你是,一个期望用户必须通过 数千 行信息的用户界面不是一个非常有用或友好的界面。例如,从 Google 显示数十万个查询命中的方式中得到启发。
我最初的方法是将我的 DataGridView 包含在一个面板内,将其高度设置在面板边界之外,然后更改控制面板的滚动条位置。但是,我刚刚发现我的 DataGridView 中的行数将达到 2000,这迫使我至少将 DataGridView 的大小调整为:
65px (row height) x 2,000 = 130,000px.
我的 64 位机器上 DataGridView 控件允许的最大大小是 65,535。任何人都可以想办法解决这个问题?
也许您可以将行高设置为大约 1 个像素,这样所有行在所有行加载时都变为 1 个像素高。然后假设您知道在 DataGridView 的最大高度中可以看到多少行你有你可以确保选择 1 行并将其放置在它的中心。然后通过循环,您可以将所选行的高度和所选行上方和下方的 x
行的高度设置为 65 像素。并在所选行发生变化时(当用户使用箭头键等时)将所选行滚动到中心并再次调整行的大小。对于这种情况,这是我能想到的唯一方法。
希望对你有所帮助
Sorry to say but this requirement is not the way a DataGridView works. You don't actually interact directly with the scrollbar.
以这段代码为例,您唯一可以控制的 属性 是 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 的顶部位置。
Unless you want users of your application getting RSI or CTS I dont see the point in scrolling so precisely.
嗯,不,不能两全其美。 65535 像素的大小限制不是人为的,它是操作系统中的硬限制。根本原因是WM_VSCROLL message。传递的 LPARAM 参数的值记录为:
The HIWORD specifies the current position of the scroll box if the LOWORD is SB_THUMBPOSITION or SB_THUMBTRACK
HIWORD为值的高16位,LOWORD为低16位。其中只能提供 0 .. Pow(2, 16)-1 = 0..65535 的范围。此限制在其他地方可见,如果您用超过(65535 + 可见)项填充列表框,它会出现不良行为。您不能再滚动到底部了。
听起来像是一个非常糟糕的问题,微软当然应该在他们的软件中修复这些可怕的限制。但是不,这不在他们的优先列表中。与 WaitHandle.WaitAny() 无法处理包含超过 64 个项目的数组这一看似奇怪的限制没有什么不同。这是故意的,他们认为你做错了,不是他们。而你是,一个期望用户必须通过 数千 行信息的用户界面不是一个非常有用或友好的界面。例如,从 Google 显示数十万个查询命中的方式中得到启发。