DataGridView在值更改时立即更改单元格颜色

时间:2017-02-06 15:41:39

标签: c# datagridview

我有一个绑定到数据源的DataGridView。我想让细胞的背面颜色改变(比如红色),只要细胞中的值发生变化就会持续1-2秒。我已经尝试过并且能够更改单元格的背面颜色,但几秒钟后无法将其恢复为默认颜色。这个想法是在用户的价值发生变化时引起用户的注意。

应用程序C#.NET 4.5

4 个答案:

答案 0 :(得分:1)

我为按钮创建了示例,但您可以将它应用于DataGridView单元格。

    private Color OriginalColor = Color.WhiteSmoke;
    private int TimeToColorInMiliSeconds = 2000;

    private void button1_Click(object sender, EventArgs e)
    {
        ColorForTwoSeconds(button1);
    }

    private void ColorForTwoSeconds(Button button)
    {
        button.BackColor = Color.Red;
        Task.Run(() => ResetBackColor());
    }

    private void ResetBackColor()
    {
        Thread.Sleep(TimeToColorInMiliSeconds);
        button1.BeginInvoke((MethodInvoker) delegate
        {
            button1.BackColor = OriginalColor;
        });   
    }

答案 1 :(得分:0)

试试这个

dataGridView1.Rows[rowIndex].Cells[columnIndex].Style.BackColor = Color.Red;

如果你想为所有行着色试试这个

dataGridView1.RowsDefaultCellStyle.SelectionBackColor = Color.Red;

答案 2 :(得分:0)

KernalMode suggested非常相似,您可以使用线程调用将单元格BackColor设置一段时间。为了确保对单元格的其他编辑在颜色更改时“重置”计时器,您可以使用上次编辑的DateTime值设置单元格的标记,并检查其经过的时间。

private int TimeToColorInMiliSeconds = 2000;

private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    this.dataGridView1[e.ColumnIndex, e.RowIndex].Tag = DateTime.Now;
    Task.Run(() => this.ChangeCellBackground(e.ColumnIndex, e.RowIndex, Color.White, Color.IndianRed));
}

private void ChangeCellBackground(int col, int row, Color original, Color alert)
{
    this.dataGridView1.BeginInvoke((MethodInvoker)delegate
    {
        this.dataGridView1[col, row].Style.BackColor = alert;
    });

    Thread.Sleep(this.TimeToColorInMiliSeconds);

    this.dataGridView1.BeginInvoke((MethodInvoker)delegate
    {
        DateTime lastChanged = (DateTime)(this.dataGridView1[col, row].Tag);
        DateTime timeNow = DateTime.Now;
        TimeSpan elapsed = timeNow - lastChanged;

        if (elapsed.TotalMilliseconds >= this.TimeToColorInMiliSeconds)
        {
            this.dataGridView1[col, row].Style.BackColor = original;
        }
    });
}

测试目的

要模拟快速更改,请考虑以下示例,其中所有单元格都初始化为0,单击按钮会开始递归函数,该函数会每隔N毫秒递增一个随机选择的单元格的值

private int N = 500;
private Random rand = new Random();

private void Button1_Click(object sender, EventArgs e)
{
    Task.Run(() => this.IncrementRandomCell());
}

private void IncrementRandomCell()
{
    int col = this.rand.Next(this.dataGridView1.ColumnCount);
    int row = this.rand.Next(this.dataGridView1.RowCount);

    this.dataGridView1.BeginInvoke((MethodInvoker)delegate
    {
        int value = int.Parse(this.dataGridView1[col, row].Value.ToString());
        this.dataGridView1[col, row].Value = ++value;
    });

    Thread.Sleep(this.N);
    this.IncrementRandomCell();
}

答案 3 :(得分:0)

这是我的方法。通过创建自己的单元格,您可以检查值是否已更改并相应地处理它。使用Forms.Timer可以避免使用线程。

由于DataGridViewCells没有OnValueChanged事件,我们重写Paint以检查值是否已更改。 如果是这样,我们更改BackColor并启动计时器以将BackColor重置为之前的值。

如您所见,我从DataGridViewTextBoxCell派生。但是重写DataGridViewCheckBoxCell或任何其他应该基本上以相同的方式工作。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace DataGridViewCustomControls
{
    internal class DataGridViewHighlightChangeCell : DataGridViewTextBoxCell    
    {
        public Color HighlightColor { get; set; } = Color.Red;
        public int HighlightTime { get; set; } = 1000;

        private object PreviousValue;
        private Color PreviousColor;
        private Timer HighlightTimer = new Timer();

        public DataGridViewHighlightChangeCell()
        {
            HighlightTimer.Tick += HighlightTimer_Tick;
        }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            HighlightOnChange();

            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }

        private void HighlightOnChange()
        {
            if (RowIndex == -1 || Value == PreviousValue)
            {
                return;
            }

            PreviousValue = Value;

            if (HighlightTimer.Enabled)
            {
                HighlightTimer.Stop();
                HighlightTimer.Start();
                return;
            }

            PreviousColor = Style.BackColor;
            Style.BackColor = HighlightColor;
            HighlightTimer.Interval = HighlightTime;
            HighlightTimer.Start();
        }

        private void HighlightTimer_Tick(object sender, EventArgs e)
        {
            HighlightTimer.Stop();
            Style.BackColor = PreviousColor;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && HighlightTimer != null)
            {
                HighlightTimer.Dispose();
                HighlightTimer = null;
            }

            base.Dispose(disposing);
        }
    }
}