关于c#:在WinForms中的控件更新期间闪烁(例如DataGridView)

关于c#:在WinForms中的控件更新期间闪烁(例如DataGridView)

Flickering during updates to Controls in WinForms (e.g. DataGridView)

在我的应用程序中,我有一个DataGridView控件,该控件显示所选对象的数据。 当选择其他对象时(在上面的组合框中),我需要更新网格。 不幸的是,不同的对象具有完全不同的数据,甚至具有不同的列,因此我需要清除所有现有数据和列,创建新列并添加所有行。 完成此操作后,整个控件将可怕地闪烁,并且需要很长时间。 有没有一种通用的方法可以使控件处于更新状态,以便它不会重新绘制自身,而是在完成所有更新后重新绘制它?

TreeViews当然是可能的:

1
2
3
4
5
6
7
8
9
myTreeView.BeginUpdate();
try
{
    //do the updates
}
finally
{
    myTreeView.EndUpdate();
}

是否有通用方法可以与其他控件(特别是DataGridView)一起使用?

更新:对不起,我不确定我是否足够清楚。 我看到"闪烁",因为在单次编辑后,控件将重新绘制在屏幕上,因此您可以看到滚动条缩小等。


人们似乎忘记了一个简单的解决方案:

1
2
3
4
5
Object.Visible = false;

//do update work

Object.Visible = true;

我知道这看起来很奇怪,但是可以。当对象不可见时,它不会重绘自身。但是,您仍然需要进行beginend更新。


.NET控件支持SuspendLayout和ResumeLayout方法。选择适当的父控件(即托管要填充的控件的控件),然后执行以下操作:

1
2
3
4
5
this.SuspendLayout();

// Do something interesting.

this.ResumeLayout();


双缓冲在这里无济于事,因为只有双缓冲绘画操作,OP看到的闪烁是多次绘画操作的结果:

  • 清除控件内容->重新绘制
  • 清除列->重涂
  • 填充新列->重新绘制
  • 添加行->重画

因此需要四次重绘以更新控件,从而实现闪烁。不幸的是,并非所有标准控件都具有BeginUpdate / EndUpdate,它将删除所有重画调用,直到调用EndUpdate。您可以执行以下操作:

  • 每个数据集都有不同的控件,并显示/隐藏控件,
  • 从其父项中删除该控件,进行更新,然后再次添加该控件,
  • 编写自己的控件。
  • 选项1和2仍会闪烁。

    在我正在使用的.Net GUI程序上,我创建了一组自定义控件,这些控件消除了所有闪烁。


    而不是一次添加一个数据网格的行,而是使用DataGridView.Rows.AddRange方法一次添加所有的行。那应该只更新一次显示。还有一个DataGridView.Columns.AddRange对列执行相同的操作。


    这对我有用。

    http://www.syncfusion.com/faq/windowsforms/search/558.aspx

    基本上,它涉及从所需的控件派生并设置以下样式。

    1
    2
    3
    SetStyle(ControlStyles.UserPaint, true);
    SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    SetStyle(ControlStyles.DoubleBuffer, true);

    不幸的是,我认为Thins可能只是.net框架的副产品。尽管使用自定义控件,但我也遇到了类似的闪烁。我阅读的许多参考资料都表明了这一点,同时双重缓冲方法无法消除任何闪烁。


    听起来像您想要双重缓冲:

    http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx

    尽管此方法主要用于单个控件,但是您可以在Windows Forms控件或Form中实现它。


    您也可以尝试此操作。

    1
    2
    3
    4
    5
    6
    public static void DoubleBuffered(Control formControl, bool setting)
    {
        Type conType = formControl.GetType();
        PropertyInfo pi = conType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(formControl, setting, null);
    }

    推荐阅读