在DataGridView垂直滚动条上绘制标记

本文关键字:绘制 滚动条 DataGridView 垂直 | 更新日期: 2023-09-27 18:10:17

我正在研究一个项目,其中DataGridView中的单元格突出显示。我想知道我是否可以在滚动条上做标记来指出那些高亮的位置。有什么想法可能会有帮助。

在DataGridView垂直滚动条上绘制标记

Yes, No and a Maybe

Yes:根据这个是可能的。然而,这只是一个链接的答案;不知道这会导致什么……

No:根据Cody Gray在他对这篇文章的回答中出色的分析,在滚动条上画画是不可能的。

但是也许可以解决你的问题…?

思路如下:

添加一个薄的Panel,它要么覆盖滚动条,要么附着在滚动条的左侧。我应该非常瘦,并且超过滚动条的高度;它会用通常的Paint事件重新绘制。

您保留了一个行列表,应该为其显示标记。此列表在以下情况下重新创建或维护:

  • 添加,去除Rows
  • 更改目标行
  • 可能在排序或过滤
  • 时出现

这里是一个小代码,只是一个快速的概念证明。对于一个更健壮的解决方案,我想我会创建一个DataGridView将注册的装饰器类。

现在,当你移动电梯到标记,你会找到目标行。还有很多改进的空间,但我觉得这是一个开始。

您必须根据需要更改isRowMarked()功能。我选择测试第一个Cell的Backcolor.

你也可以很容易地使用不同的颜色来标记不同的标记;也许可以从标记的行/单元格中复制它们。

public Form1()
{
    InitializeComponent();
    dataGridView1.Controls.Add(indicatorPanel);
    indicatorPanel.Width = 6;
    indicatorPanel.Height = dataGridView1.ClientSize.Height - 39;
    indicatorPanel.Top = 20;
    indicatorPanel.Left = dataGridView1.ClientSize.Width - 21;
    indicatorPanel.Paint += indicatorPanel_Paint;
    dataGridView1.Paint += dataGridView1_Paint;
}
Panel indicatorPanel = new Panel();
List<DataGridViewRow> tgtRows = new List<DataGridViewRow>();
void dataGridView1_Paint(object sender, PaintEventArgs e)
{
    indicatorPanel.Invalidate();
}
void indicatorPanel_Paint(object sender, PaintEventArgs e)
{   // check if there is a HScrollbar
    int hs = ((dataGridView1.ScrollBars & ScrollBars.Vertical) != ScrollBars.None ? 20 : 0);
    e.Graphics.FillRectangle(Brushes.Silver, indicatorPanel.ClientRectangle);
    foreach (DataGridViewRow tRow in tgtRows)
    {
        int h = (int)(1f * (indicatorPanel.Height - 20 + hs) * tRow.Index 
                         / dataGridView1.Rows.Count);
        e.Graphics.FillRectangle(Brushes.Red, 0, h-3, 6, 4);
    }
}
bool isRowMarked(DataGridViewRow row)
{
    return row.Cells[0].Style.BackColor == Color.Red;  // <<-- change!
}
// call in: dataGridView1_RowsRemoved, dataGridView1_RowsAdded
// also whenever you set or change markings and after sorting or a filtering
void findMarkers()
{
    tgtRows.Clear();
    foreach (DataGridViewRow row in dataGridView1.Rows)
        if (isRowMarked(row) ) tgtRows.Add(row); 
    indicatorPanel.Invalidate();
}

注释我已经删除了第一个答案,因为原始要求谈论"标记"而不仅仅是"几个标记"。现在,第二个版本对我来说似乎好多了。