在我正在开发的应用程序中,我正在使用datagridview来显示数据。为了填充它,我要按一个按钮,后台工作人员将开始运行,它将填充一个数据表,当它完成运行时,它将使用数据表作为数据网格的数据源。这很好用,用户界面保持响应等等。 但是现在我已经对行进行了着色,这取决于它们的值(我还在玩它,所以欢迎任何建议):
private void ApplyColoring()
{
if (dataGridView1.DataSource != null)
{
foreach (DataGridViewRow dataGridRow in dataGridView1.Rows)
{
// hardmap a color to a column
IDictionary<Int32, Color> colorDictionary = new Dictionary<Int32, Color>();
colorDictionary.Add( 7, Color.FromArgb(194, 235, 211));
colorDictionary.Add( 8, Color.Salmon);
colorDictionary.Add( 9, Color.LightBlue);
colorDictionary.Add(10, Color.LightYellow);
colorDictionary.Add(11, Color.LightGreen);
colorDictionary.Add(12, Color.LightCoral);
colorDictionary.Add(13, Color.Blue);
colorDictionary.Add(14, Color.Yellow);
colorDictionary.Add(15, Color.Green);
colorDictionary.Add(16, Color.White);
foreach (DataGridViewRow gridRow in dataGridView1.Rows)
{
foreach (DataGridViewCell cell in gridRow.Cells)
{
if (colorDictionary.Keys.Contains(cell.ColumnIndex))
{
// standard background
cell.Style.BackColor = Color.FromArgb(194, 235, 211);
}
}
}
IList<String> checkedValues = new List<String>();
// first we loop through all the rows
foreach (DataGridViewRow gridRow in dataGridView1.Rows)
{
IDictionary<String, Int32> checkedVal = new Dictionary<String, Int32>();
// then we loop through all the data columns
int maxCol = dnsList.Count + 7;
for (int columnLoop = 7; columnLoop < maxCol; columnLoop++)
{
string current = gridRow.Cells[columnLoop].Value.ToString();
for (int checkLoop = 7; checkLoop < maxCol; checkLoop++)
{
string check = gridRow.Cells[checkLoop].Value.ToString();
if (!current.Equals(check))
{
if (checkedVal.Keys.Contains(current))
{
gridRow.Cells[columnLoop].Style.BackColor = colorDictionary[checkedVal[current]];
}
else
{
gridRow.Cells[columnLoop].Style.BackColor = colorDictionary[columnLoop];
checkedVal.Add(current, columnLoop);
}
}
}
}
}
}
}
}
这给了我一些问题。不是因为着色不起作用,确实如此。但是因为它让它变得很慢。它第一次运行正常,但当我再次按下按钮时,它很慢,因为地狱和数据网格闪烁。 我希望这个运行作为后期处理,所以它(或者应该)在后台工作完成后运行。 但是当我从RunWorkerCompleted事件中调用applycoloring时,它只是很慢。我应该怎么做才能防止这种情况发生?如何在执行新查询时确保UI不闪烁(同时不丢失网格中的当前数据)。
答案 0 :(得分:17)
你可以打开双缓冲。
VB:
Imports System.Reflection
如下所示在Form_Load
中Dim systemType As Type = DataGridView1.GetType()
Dim propertyInfo As PropertyInfo = systemType.GetProperty("DoubleBuffered", BindingFlags.Instance Or BindingFlags.NonPublic)
propertyInfo.SetValue(DataGridView1, True, Nothing)
对于C#:转到:Fixing a slow scrolling DataGridView
干杯
答案 1 :(得分:5)
两个建议:
答案 2 :(得分:4)
我找到了另一种为慢数据网格做反射双缓冲的方法:
使用一些反射创建一个扩展方法,以在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: http://www.codeproject.com/Tips/390496/Reducing-flicker-blinking-in-DataGridView
答案 3 :(得分:1)
尝试在更新前调用SuspendLayout。别忘了打电话给ResumeLayout。
答案 4 :(得分:1)
我强烈建议不要在网格上循环(双缓冲可能会有所帮助,但它只是“隐藏”了真正的问题),因为它会产生大量渲染。
出于这样的目的,我使用了一个事件处理程序:
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;
}
}
只要您的单元格值发生变化,网格就会自动更新并更改背景颜色
答案 5 :(得分:1)
开启双缓冲
编译函数所需的命名空间列表是:
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);