Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.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# 如何防止datagrid中的行在应用程序运行时闪烁_C#_Winforms_Multithreading_Datagrid_Flicker - Fatal编程技术网

C# 如何防止datagrid中的行在应用程序运行时闪烁

C# 如何防止datagrid中的行在应用程序运行时闪烁,c#,winforms,multithreading,datagrid,flicker,C#,Winforms,Multithreading,Datagrid,Flicker,在我正在开发的应用程序中,我正在使用datagridview显示数据。为了填充它,我必须按下一个按钮,backgroundworker将开始运行,它将填充一个datatable,当它完成运行时,它将使用datatable作为datagrid的数据源。这很好,用户界面保持响应性等等。 但是现在我已经实现了对行的着色,这取决于它们的值(我仍然在玩它,所以欢迎任何建议): private void ApplyColoring() { if(dataGridView1.DataSource!=null)

在我正在开发的应用程序中,我正在使用datagridview显示数据。为了填充它,我必须按下一个按钮,backgroundworker将开始运行,它将填充一个datatable,当它完成运行时,它将使用datatable作为datagrid的数据源。这很好,用户界面保持响应性等等。 但是现在我已经实现了对行的着色,这取决于它们的值(我仍然在玩它,所以欢迎任何建议):

private void ApplyColoring()
{
if(dataGridView1.DataSource!=null)
{
foreach(DataGridViewRow dataGridRow在dataGridView1.Rows中)
{
//将颜色硬映射到列
IDictionary colorDictionary=新字典();
添加(7,Color.FromArgb(194235 211));
颜色字典。添加(8,颜色。三文鱼);
颜色字典。添加(9,颜色。浅蓝色);
颜色字典。添加(10,颜色。浅黄色);
颜色字典。添加(11,颜色。浅绿色);
添加(12,Color.LightCoral);
颜色字典。添加(13,颜色。蓝色);
颜色字典。添加(14,颜色。黄色);
颜色字典。添加(15,颜色。绿色);
颜色字典。添加(16,颜色。白色);
foreach(DataGridViewRow gridRow在dataGridView1.Rows中)
{
foreach(gridRow.Cells中的DataGridViewCell单元格)
{
if(colorDictionary.Keys.Contains(cell.ColumnIndex))
{
//标准背景
cell.Style.BackColor=Color.FromArgb(194235 211);
}
}
}
IList checkedValues=新列表();
//首先,我们遍历所有行
foreach(DataGridViewRow gridRow在dataGridView1.Rows中)
{
IDictionary checkedVal=新字典();
//然后我们循环遍历所有的数据列
int maxCol=dnsList.Count+7;
for(int columnLoop=7;columnLoop
这给我带来了麻烦。不是因为颜色不起作用,而是起作用了。但是因为它让它变得很慢。第一次它运行正常,但当我再次按下按钮时,速度非常慢,datagrid正在闪烁。 我希望此运行作为后处理,因此它(或者更确切地说应该)在backgroundworker完成后运行。 但是当我从RunWorkerCompleted事件调用ApplyColor时,它的速度很慢。我该怎么做才能解决这个问题?如何确保UI在执行新查询时不会闪烁(同时不会丢失网格中的当前数据)。

两个建议:

  • 尝试在循环之前调用SuspendLayout(),在循环之后调用ResumeLayout()。大多数其他控件调用此BeginUpdate()和EndUpdate()(列表视图、组合框等)
  • 如果要处理大量数据,请在DataGridView上使用VirtualMode 数据

  • 尝试在更新之前调用SuspendLayout。不要忘记调用ResumeLayout。

    您可以启用双缓冲

    VB:

    将以下内容放入表格中,例如

    Dim systemType As Type = DataGridView1.GetType()
    Dim propertyInfo As PropertyInfo = systemType.GetProperty("DoubleBuffered", BindingFlags.Instance Or BindingFlags.NonPublic)
    propertyInfo.SetValue(DataGridView1, True, Nothing)
    
    对于C#:转到:


    干杯

    我找到了另一种方法来为慢速数据网格执行反射双缓冲:

    创建一个带有反射的扩展方法,以在datagrid上设置双缓冲:

    public static class DataGridViewExtensioncs
    {
    
        public static void DoubleBuffered(this DataGridView dgv, bool setting)
        {
            var dgvType = dgv.GetType();
            var pi = dgvType.GetProperty("DoubleBuffered",
                  BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(dgv, setting, null);
        }
    }
    
    然后以初始值设定项的形式执行以下操作:

    this.dataGrid.DoubleBuffered(true);
    
    这与Evolved的答案非常相似,Shweta Lodha获得了积分:

    我强烈建议不要在网格上循环(双缓冲可能会有所帮助,但它只是“隐藏”了真正的问题),因为它会产生大量渲染

    出于类似目的,我使用eventhandler:

    dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
    
    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
                if (dataGridView1.Columns[5].Index == e.ColumnIndex && e.RowIndex >= 0 && dataGridView1[5, e.RowIndex].Value.ToString() != "0")
                {
                    e.CellStyle.BackColor = Color.PaleGreen;
                }
        }
    

    每当单元格值更改时,网格将自动更新并更改背景颜色

    启用双缓冲

    要编译的函数所需的名称空间列表为:

    using System;
    using System.Reflection;
    using System.Windows.Forms;
    
    public static class ExtensionMethods
    {
       public static void DoubleBuffered(this DataGridView dgv, bool setting)
       {
          Type dgvType = dgv.GetType();
          PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
          pi.SetValue(dgv, setting, null);
       }
    }
    
    然后初始化datagridview

    dataGridView1.DoubleBuffered(true);
    

    除了suspendlayout(),还要避免所有这些嵌套循环(我不知道它真正的作用是什么,但看起来太复杂了,不需要)。此外,所有这些.ToString()可能会降低一些性能。您可能会删除第一个foreach循环,因为它似乎什么也不做,只会显著增加循环的数量!!!foreach(DataGridViewRow dataGridRow在dataGridView1.Rows中)你完全正确,我删除了2个foreach循环。标准颜色不必在单独的循环中+最上面的foreach完全没有用处:)我将研究ToString()备注:)我的问题类似,但我的场景不同。当大小为时,DataGridView不会停止闪烁
    using System;
    using System.Reflection;
    using System.Windows.Forms;
    
    public static class ExtensionMethods
    {
       public static void DoubleBuffered(this DataGridView dgv, bool setting)
       {
          Type dgvType = dgv.GetType();
          PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
          pi.SetValue(dgv, setting, null);
       }
    }
    
    dataGridView1.DoubleBuffered(true);