【问题标题】:Why do I get different results when I run the same code in a TextChanged event as opposed to a Button Click?为什么我在 TextChanged 事件中运行相同的代码而不是 Button Click 时会得到不同的结果?
【发布时间】:2019-07-01 18:38:51
【问题描述】:

我有一个函数可以遍历 Datagridview 并找到与提供的搜索查询匹配的任何内容。 它使用它找到的“命中”在 datagridview 的右侧绘制一个面板,显示命中相对于滚动条的位置。

当我在按钮单击事件中运行此代码时,它按预期工作。 当我在文本更改事件中运行它时,代码按预期运行,然后面板自行清除。

这仅在每个调试会话第一次运行代码时发生。会话的其余部分,文本更改事件工作正常,面板保留了它应该绘制的部分。

最初,出于开发目的,我将代码直接放在按钮事件处理程序中。只有当我在文本更改事件中放置相同的代码时,我才第一次看到这个问题。

我已经将代码放入它自己的函数中,在按钮单击和文本更改事件中调用它。

所以它看起来像这样:

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,显示了当我在一个简单的 Button Click 中运行搜索时会发生什么:
Panel Paint on Button Click event

你会注意到,我点击了按钮,面板保留了它的颜色。

如果我将相同的代码放入 TextChanged 事件处理程序会发生以下情况:
Panel Paint on TextChanged event

它在达到 3 个字符之前不会搜索,所以你会看到,一旦我输入“U”,它就会运行搜索,绘制面板,然后立即清除它。所有其他搜索,例如当我添加“E”或退格回到“U”时都可以正常工作。

【问题讨论】:

  • PanelPaint_paint() 是有趣的部分。
  • 我不能说为什么它的工作方式不同。但是有一个简单的规则 - only 在需要绘画的控件的Paint 事件中进行绘画并且不会有副作用/奇怪的行为。
  • @myaccountname Jimi 要求您复制PanelPaint_paint() 方法的源代码并将其粘贴到您的问题中。您可以编辑问题以添加更多文本。
  • @Jimi 已添加!我是新手,想尽可能地隐藏我的意大利面……如果有不清楚的地方告诉我。
  • @myaccountname 这就像咨询医生。不要尴尬。他的情况更糟。

标签: c# winforms graphics gdi+


【解决方案1】:

当您以这种方式创建 Graphics 对象时:

Graphics g = panelPaint.CreateGraphics();

您使用此对象绘制的内容不会持续存在。控件每次重绘(无效)时都会生成一个新的 Graphics 对象。这种情况经常发生。这意味着每次控件失效时都需要刷新绘图,使用Paint 事件的PaintEventArgs 提供的当前图形对象。 (您经常会在 MSDN Docs 和 StackOverflow 中的许多问题中找到此建议。

因此,您总是在Paint 处理程序(或被覆盖的OnPaint 方法)中执行所有绘制。

不同的事件可能导致控件无效(重绘):当窗体最小化/最大化时,当另一个对象/窗口在其上移动时,当系统广播设置更改消息(和其他)时以及许多其他条件。

当表单的AutoValidate 功能触发它时:

获取或设置一个值,该值指示此容器中的控件是否 焦点改变时会自动验证。

尝试如下修改代码。请注意,我无法测试此代码,因为我没有对象和此处使用的某些值。我希望这可以帮助您调整代码。

private void Search() {
    _hits.Clear();
    tbTotal.Visible = false;
    if (tbSearch.Text.Length < 3) return;
    Searchy(tbSearch.Text);
    if (_hits.Count == 0) return;

    foreach (var hit in _hits) {
        dgvEvents.Rows[hit.RowNum].Cells[2].Style = new DataGridViewCellStyle {
            BackColor = hit.color == Color.Empty ? ext.myColor : hit.color,
            ForeColor = invert(BackColor)
        };
    }
    panelPaint.Invalidate();
    extrabuttons(true);
    tbTotal.Text = allhits().Count.ToString();
}

private void panelPaint_Paint(object sender, PaintEventArgs e)
{
    if (_hits.Count == 0) return;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    foreach (var hit in _hits) {
        PaintPanel(hit, e.Graphics);
    }
}

private void PaintPanel(Hit hit, Graphics g)
{
    using (Pen myPen = new Pen(hit.color == Color.Empty ? ext.myColor : hit.color, 1)) {
        float percent = ((float)hit.RowNum / dgvEvents.Rows.Count) * (float)panelPaint.Height;
        g.DrawLine(myPen, 1, percent, panelPaint.Width, percent);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多