C# 在WinForms(例如DataGridView)中更新控件时闪烁

C# 在WinForms(例如DataGridView)中更新控件时闪烁,c#,.net,winforms,C#,.net,Winforms,在我的应用程序中,我有一个DataGridView控件,用于显示选定对象的数据。当我选择一个不同的对象(在上面的组合框中)时,我需要更新网格。不幸的是,不同的对象有完全不同的数据,甚至不同的列,所以我需要清除所有现有的数据和列,创建新的列并添加所有的行。当这项工作完成时,整个控件会可怕地闪烁,而且需要很长时间。有没有一种通用方法可以让控件处于更新状态,这样它就不会重新绘制自己,然后在我完成所有更新后重新绘制它 使用TreeView当然是可能的: myTreeView.BeginUpdate();

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

使用TreeView当然是可能的:

myTreeView.BeginUpdate();
try
{
    //do the updates
}
finally
{
    myTreeView.EndUpdate();
}
对于其他控件,尤其是DataGridView,是否有一种通用的方法可以做到这一点


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

听起来您需要双缓冲:


尽管这主要用于单个控件,但您可以在Windows窗体控件或窗体中实现它。

不幸的是,我认为thins可能只是.net framework的副产品。我正在经历类似的闪烁,尽管有自定义控件。我读过的许多参考资料都表明了这一点,同时双缓冲方法也未能为我消除任何闪烁。

双缓冲在这里没有帮助,因为只有双缓冲绘制操作,OP看到的闪烁是多个绘制操作的结果:

  • 清除控件内容->重新绘制
  • 清除列->重新绘制
  • 填充新列->重新绘制
  • 添加行->重新绘制
这是更新控件的四个重绘,因此闪烁。不幸的是,并非所有标准控件都具有BeginUpdate/EndUpdate,它将删除所有重绘调用,直到调用EndUpdate为止。以下是您可以做的:

  • 为每个数据集使用不同的控件,并显示/隐藏控件
  • 从其父控件中删除该控件,更新并再次添加该控件
  • 编写自己的控件
  • 选项1和2仍会闪烁一点


    在我正在开发的.NETGUI程序中,我创建了一组自定义控件,消除了所有闪烁

    该.NET控件支持和方法。选择适当的父控件(即承载要填充的控件的控件)并执行以下操作:

    this.SuspendLayout();
    
    // Do something interesting.
    
    this.ResumeLayout();
    

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

    这对我很有用

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

    SetStyle(ControlStyles.UserPaint, true);
    SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
    SetStyle(ControlStyles.DoubleBuffer, true); 
    

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

    Object.Visible = false;
    
    //do update work
    
    Object.Visible = true;
    

    我知道这看起来很奇怪,但这很管用。当对象不可见时,它不会重新绘制自身。但是,您仍然需要执行
    开始
    结束
    更新。

    您也可以尝试这项工作

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

    我尝试了双缓冲,但没有多大帮助。我认为问题在于,它在我添加的每一行之后都会尝试重新绘制,因此它最终会多次更新第一行。是的,我很确定这就是问题所在。因为我必须添加>50行,所以可以看到网格是如何增长的。当您创建控件时,您扩展了现有的数据网格视图,或者从头开始编写了一个新的数据网格视图?我从头开始编写它们,源自UserControl,它们都是非常特定于应用程序的。干杯,这似乎是DataGridViews可以获得的最好结果。这应该有更多的要点,会为我节省很多时间。其他建议对我的用例不起作用,但这是完美的。谢谢将其添加到DataGridView双缓冲区中(true);