我有一个函数,它遍历数据网格视图并查找与所提供的搜索查询匹配的任何匹配项。它使用找到的“命中”在数据网格视图的右侧绘制一个面板,显示命中相对于滚动条的位置。
当我在按钮单击事件中运行这段代码时,它会按预期工作。当我在文本更改事件中运行它时,代码会按预期运行,然后面板会自行清除。
这只发生在每个调试会话第一次运行代码时。在会话的其余部分,文本更改事件工作正常,面板保持其绘制的部分,因为它应该。
最初,出于开发的目的,我将代码直接放在按钮事件处理程序中。只有当我将相同的代码放在文本更改事件中时,我才第一次看到这个问题。
此后,我将代码放入它自己的函数中,在按钮单击和文本更改事件中调用它。
所以它看起来像这样:
private void btnSearch_Click(object sender, EventArgs e)
{
Search();
}
private void TbSearch_TextChanged(object sender, EventArgs e)
{
Search();
}
“搜索”包含:
private void Search()
{
PanelClear();
if (tbSearch.Text.Length > 2)
{
Searchy(tbSearch.Text);
if (_hits.Count > 0)
{
foreach (var hit in _hits){PanelPaint_paint(hit);}
}
}
}
PanelClear
包含:
private void PanelClear()
{
//Clears the list of matches.
_hits.Clear();
//Invalidates my panel control.
panelPaint.Invalidate();
//Hides a textbox
tbTotal.Visible = false;
}
以及PanelPaint_paint
:
private void PanelPaint_paint(Hit hit)
{
Graphics g = panelPaint.CreateGraphics();
Color xx = ext.myColor;
Color saved = hit.color;
if (saved != Color.Empty) xx = hit.color;
Pen myPen = new Pen(xx) { Width = 1 };
int dgvl = dgvEvents.Rows.Count;
int pnll = panelPaint.Height;
int hitl = hit.RowNum;
double percent = ((double)hitl / (double)dgvl) * pnll;
float x = (float)percent;
g.DrawLine(myPen, 1, x, panelPaint.Width, x);
dgvEvents.Rows[hit.RowNum].Cells[2].Style = new DataGridViewCellStyle
{
BackColor = xx,
ForeColor = invert(xx)
};
extrabuttons(true);
tbTotal.Text = allhits().Count.ToString();
}
这里有一个gif图片,显示了当我在一个简单的按钮点击中运行搜索时会发生什么:
Panel Paint on Button Click event
您会注意到,我单击按钮,面板保留其绘制。
如果我将相同的程式码放入TextChanged事件行程常式,会发生下列情况:
Panel Paint on TextChanged event
它不会搜索,直到它达到3个字符,所以你会看到,一旦我输入'U'它运行搜索,绘制面板,但然后立即清除它。所有其他搜索,如当我添加'E',或退格键回到'U'工作正常。
1条答案
按热度按时间zf9nrax11#
当您以下列方式建立Graphics对象时:
使用该对象绘制的内容将无法保留。控件每次重绘时都会生成一个新的Graphics对象(invalidated)。这种情况经常发生。这意味着每次控件失效时,都需要使用
Paint
事件的PaintEventArgs提供的当前Graphics对象刷新绘图。(您经常可以在MSDN文档和StackOverflow的许多问题中找到此建议)。因此,您总是在
Paint
处理函数(或被重写的OnPaint方法)中执行所有绘制。不同的事件可能导致控件失效(重新绘制):当窗体最小化/最大化时,当另一个对象/窗口移动到它上面时,当系统广播设置更改消息(和其他消息)时,以及许多其他条件。
此外,当Forms的AutoValidate功能触发它时:
获取或设置一个值,该值指示当焦点更改时是否自动验证此容器中的控件。
尝试修改代码如下。注意,我不能测试这段代码,因为我没有这里使用的对象和一些值。我希望这能帮助你调整你的代码。