获取指定Y坐标的DataGridView行

时间:2015-04-17 10:23:30

标签: .net datagridview location vertical-scrolling

问题

我正在尝试将外部垂直滚动条链接到datagridview。我需要一个外部滚动条,因为我希望它是否经常可见,无论是否有多余的行。我开始时听起来很简单,但我在调整行大小时遇到​​了麻烦。

尝试

我试图每行滚动(最多滚动条是行数,小变化是1,大变化是显示行的数量)。这不起作用,因为它能够调整行的大小,因为这会改变显示的行数,从而设置较大的更改,从而搞砸滚动条。

我得出结论,最好的方法是按像素值滚动。默认的DGV行为按行而不是像素滚动所以我需要将像素值转换为行索引,以便我可以设置FirstDisplayedScrollingRowIndex属性。但是,我正在寻找一种方法来获取特定点的行。我已经尝试过HitTestInfo,但这似乎只适用于显示的行,而不适用于不在视图范围内的行。

到目前为止,我发现这样做的最好方法是Lambda循环遍历行并找到哪一行落在Y坐标内。

    Dim Block As Integer = If(DGV.ColumnHeadersVisible, -DGV.ColumnHeadersHeight, 0)
    Dim ScrollToRow As DataGridViewRow = DGV.Rows.Cast(Of DataGridViewRow).FirstOrDefault(Function(x)
                                                                                              Block += x.Height
                                                                                              Return Block >= VSB.Value
                                                                                          End Function)
    DGV.FirstDisplayedScrollingRowIndex = If(ScrollToRow IsNot Nothing, ScrollToRow.Index, 0)

问题

我是否缺少一个可以通过Y坐标给我一行或其索引的方法?显然,这应包括当前未显示的行。

或者,关于我如何做到这一点的任何其他建议?

1 个答案:

答案 0 :(得分:0)

下面的静态功能已在VS-2019 WinForms中测试(带有和不带有可见的DataGridView标头)。像素位置(X,Y)必须相对于控件的客户区域。该函数将在(X,Y)处生成行和列的(cr,cc)

  • 当像素位置(X,Y)在网格的行标题或列标题中时,它将返回TRUE(我们在网格中),而对应的行(cr)或列(cc)则返回-1协调。
  • 当像素位置(X,Y)在网格的数据部分内部时,它还将返回TRUE并提供从(0,0)开始的(cr,cc)。

  • 当指定像素在网格区域之外时,此函数将产生FALSE。

问题的语言未标记,因此我使用C#而不是Basic提供函数。

    private static bool FindPixelPositionInGrid(DataGridView dg, int X, int Y, out int cr, out int cc)
    {
        int rblck = dg.ColumnHeadersVisible ? dg.ColumnHeadersHeight : 0;
        bool foundcr = false;
        cc = cr = -1;
        foreach (DataGridViewRow r in dg.Rows)
        {
            if (rblck > Y) break;
            rblck += r.Height; cr++;
        }
        if (rblck > Y)
        {
            cc = -1;
            var cblck = dg.RowHeadersVisible ? dg.RowHeadersWidth : 0;
            foreach (DataGridViewColumn c in dg.Columns)
            {
                if (cblck > X)
                {
                    foundcr = true;
                    break;
                }
                cblck += c.Width; cc++;
            }
            if (cblck > X) foundcr = true;
        }
        return foundcr;
    }