Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在DataGridView垂直滚动条上绘制标记_C#_.net_Winforms_Datagridview_Scrollbar - Fatal编程技术网

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

C# 在DataGridView垂直滚动条上绘制标记,c#,.net,winforms,datagridview,scrollbar,C#,.net,Winforms,Datagridview,Scrollbar,我正在从事一个项目,其中DataGridView中的单元格会高亮显示。我想知道我是否可以在滚动条上做标记来指示那些高光在哪里。任何想法都可能有用。是、否和a可能 答案是肯定的:根据它的说法是可能的。然而,这是唯一的答案;我不知道这会导致什么 答案是否定的:根据科迪·格雷(Cody Gray)在回答在滚动条上绘画时的出色分析,这是不可能的 但也许一个变通办法可以解决你的问题 以下是想法: 您可以添加一个薄面板,该面板可以覆盖滚动条,也可以将其自身附加到滚动条的左侧。我应该很瘦,超过阴囊的高度;它会

我正在从事一个项目,其中DataGridView中的单元格会高亮显示。我想知道我是否可以在滚动条上做标记来指示那些高光在哪里。任何想法都可能有用。

是、否和a可能

答案是肯定的:根据它的说法是可能的。然而,这是唯一的答案;我不知道这会导致什么

答案是否定的:根据科迪·格雷(Cody Gray)在回答在滚动条上绘画时的出色分析,这是不可能的

但也许一个变通办法可以解决你的问题

以下是想法:

您可以添加一个薄面板,该面板可以覆盖滚动条,也可以将其自身附加到滚动条的左侧。我应该很瘦,超过阴囊的高度;它会通过通常的绘制事件重新绘制

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

添加和删除行 更改目标行 可能是在排序或筛选时 这里是一个小代码,只是一个概念的快速证明。为了获得更健壮的解决方案,我想我应该创建一个decorator类,DataGridView将注册到该类

现在,当您将升降机移向标记时,您将找到目标行。有很大的改进空间,但只是一个开始

您必须根据需要更改isRowMarked函数。我已选择测试第一个单元格的背景色

您还可以轻松地为不同的标记使用不同的颜色;可能通过从标记的行/单元格复制它们

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();
}
注:我删除了第一个答案,因为最初的要求谈论的是“分数”,而不仅仅是“几个分数”。现在,第二个版本对我来说似乎好多了。

是、否和a可能

答案是肯定的:根据它的说法是可能的。然而,这是唯一的答案;我不知道这会导致什么

答案是否定的:根据科迪·格雷(Cody Gray)在回答在滚动条上绘画时的出色分析,这是不可能的

但也许一个变通办法可以解决你的问题

以下是想法:

您可以添加一个薄面板,该面板可以覆盖滚动条,也可以将其自身附加到滚动条的左侧。我应该很瘦,超过阴囊的高度;它会通过通常的绘制事件重新绘制

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

添加和删除行 更改目标行 可能是在排序或筛选时 这里是一个小代码,只是一个概念的快速证明。为了获得更健壮的解决方案,我想我应该创建一个decorator类,DataGridView将注册到该类

现在,当您将升降机移向标记时,您将找到目标行。有很大的改进空间,但只是一个开始

您必须根据需要更改isRowMarked函数。我已选择测试第一个单元格的背景色

您还可以轻松地为不同的标记使用不同的颜色;可能通过从标记的行/单元格复制它们

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();
}

注:我删除了第一个答案,因为最初的要求谈论的是“分数”,而不仅仅是“几个分数”。现在,第二个版本对我来说似乎好多了。

请不要忘记提及,与石器时代的古老winforms相反,使用适当的数据绑定是完全可行的,并且不涉及任何可怕的过程代码黑客;给定DataGrid中的固定行大小高度,如果没有固定行大小高度,这将变得更加复杂,这只是var margin=new Thickness0,rowIndex*rowHeight,0,0;在IValueConverter中。非常类似于我在Time Range ToVerticalMarginConverter类中垂直定位预订的方式。不要猜测。做吧!顺便说一句,你的回答让我怀疑你是否理解了这个问题。使用行高不应该是等式的一部分。。实际上,一个完整的解决方案有4行C代码,其中包括通过复选框切换每行的高亮显示;请不要忘记提到,与石器时代的古老winforms相反,使用适当的数据绑定是完全可行的,并且不涉及任何可怕的过程代码黑客;给定DataGrid中的固定行大小高度,如果没有固定行大小高度,这将变得更加复杂,这只是var margin=new Thickness0,rowIndex*rowHeight,0,0;在IValueConverter中。非常类似于我在Time Range ToVerticalMarginConverter类中垂直定位预订的方式。不要猜测。做吧!顺便说一句,你的回答让我怀疑你是否理解了这个问题。使用行高不应该是等式的一部分。。实际上,一个完整的解决方案有4行C代码,其中包括通过复选框切换每行的高亮显示;