Click here to Skip to main content
12,627,681 members (35,736 online)
Click here to Skip to main content
Add your own
alternative version

Stats

99.9K views
2.3K downloads
106 bookmarked
Posted

Cell Blink for DataGridView

, 4 May 2008 Zlib
Rate this:
Please Sign up or sign in to vote.
An article on adding a cell blink feature for DataGridView
Screenshot - DataGridViewCellBlink.jpg

Introduction

After reading many articles on The Code Project, I realized that it's my time to contribute. Few months ago, I came across a requirement for cells in a DataGridView control to blink when the cell value changed. The code presented here can be applied to any other grid.

The blinking of the grid cell is achieved in the following manner. When we update the value of a cell, we also change the background color of that cell to a blink color. To restore the cell background color to its original value, we run a background thread that iterates through a list of cells that are blinking and resets them to their original non blinking state.

The Code

The sample project has two functions. The first function DataInputThreadFunc() is used to generate random values to be filled / updated in the grid. The second function GridBlinkThreadFunc() is used to restore the cells to the non blink state.

Let's take a look at the first function DataInputThreadFunc():

private void DataInputThreadFunc()
{
    Random rand = new Random();
    while (true)
    {
        if (dataGridView1.IsDisposed)
            break;

        CellData data = new CellData();
        data.Row = rand.Next(0, 7);
        data.Col = rand.Next(0, 3);
        data.Time = DateTime.Now;

        int value = rand.Next(0, 101);

        dataGridView1.Invoke((MethodInvoker)delegate()
        {
            dataGridView1.Rows[data.Row].Cells[data.Col].Value = value;
            dataGridView1.Rows[data.Row].Cells[data.Col].Style
              .BackColor = Color.Salmon;
        });

        lock (_blinkData)
        {
            _blinkData.Add(data);
        }

        Thread.Sleep(1000);
    }
}

The function uses a while (true) loop as it's a background thread and will be shutdown automatically when the application is closed. if (dataGridView1.IsDisposed) check is done to make sure we do not call dataGridView1.Invoke() on a disposed object. This can happen when the user closes the application.

Next, we initialize an object of the class CellData to store the blink data:

class CellData
{
     public int Row;
     public int Col;
     public DateTime Time;
}

This class is used to store the row number, column number and the time when the value changed.

Next we use dataGridView1.Invoke() to make a call to the user interface thread and set the grid properties. We save the blink data in a generic list to be used later by the blink thread function. Since the list is altered by more than one thread, we synchronize access by locking the list on each access.

Now let's take a look at the blink thread function:

private void GridBlinkThreadFunc()
{
    while (true)
    {
        // Make a copy to avoid invalid operation exception
        // while iterating through the map
        List<CellData> tempBlinkData;
        lock (_blinkData)
        {
            tempBlinkData = new List<CellData>(_blinkData);
        }

        foreach (CellData data in tempBlinkData)
        {
            TimeSpan elapsed = DateTime.Now - data.Time;
            if (elapsed.TotalMilliseconds > 500) // 500 is the Blink delay
            {
                if (dataGridView1.IsDisposed)
                    return;

                dataGridView1.BeginInvoke((MethodInvoker)delegate()
                {
                    dataGridView1.Rows[data.Row].Cells[data.Col]
                      .Style.BackColor = dataGridView1.Columns[data.Col]
                      .DefaultCellStyle.BackColor;
                });

                lock (_blinkData)
                {
                    _blinkData.Remove(data);
                }
            }
        }

        Thread.Sleep(250); // Blink frequency
    }
}

At the very beginning, we make a copy of the _blinkData list. This helps us to modify the list while we iterate through the contents of the temporary copy. For each cell we find in the list, we check to make sure whether the blink time has elapsed or not. In this case, the blink time is 500 milliseconds. Any cell that has elapsed the blink time gets its background color reset to the default cell style background color and is removed from the list.

Again we make sure that we set the grid property only in the user interface thread. In addition, we lock the _blinkData list before altering it. Thread.Sleep(250) is the frequency with which we go through the list to turn off the cells. Ideally, it should be half the value of blink delay.

Points of Interest

You will notice that this code can be applied to any grid. This code can also be hidden in a class that extends a DataGridView control.

One thing I love about .NET 2.0 is dataGridView1.Invoke((MethodInvoker)delegate(). This statement lets you get away from writing a function and declaring a delegate.

A good point was made by "Kristof Verbiest" about the use of BeginInvoke() instead of Invoke(). The GridBlinkThreadFunc() uses BeginInvoke() to avoid unnecessary context switch.

History

  • 09/06/2007: First published
  • 09/11/2007: Changed the GridBlinkThreadFunc() to use BeginInvoke() instead of Invoke()
  • 05/02/2008: Edited the "Points of Interest" section

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

Share

About the Author

Rammohan Raja
Architect
United States United States
Nothing to brag about, just another passionate software developer.

Work to make a living, don't live to work!

You may also be interested in...

Comments and Discussions

 
GeneralPerformance issue Pin
Hoa Le10-Nov-08 16:19
memberHoa Le10-Nov-08 16:19 
GeneralRe: Performance issue Pin
Raghavan Ram Raja14-Nov-08 4:21
memberRaghavan Ram Raja14-Nov-08 4:21 
GeneralRe: Performance issue Pin
Hoa Le20-Nov-08 18:27
memberHoa Le20-Nov-08 18:27 
GeneralVB.NET Version Here (Visual Studio 2005) Pin
gratro14-Oct-08 3:26
membergratro14-Oct-08 3:26 
A great Article.. (I have converted the code to VB for those VB coders amongst us)

Use this in the Form1.vb code.....

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Imports System.Threading

Public Class Form1

Private _dataInputThread As Thread = Nothing
Private _gridBlinkThread As Thread = Nothing
Private _blinkData As List(Of CellData) = Nothing

Public Class CellData
Public Row As Integer
Public Col As Integer
Public Time As DateTime
End Class

Public Sub New()
InitializeComponent()
_blinkData = New List(Of CellData)()
DataGridView1.RowCount = 7
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
_dataInputThread = New Thread(New ThreadStart(AddressOf DataInputThreadFunc))
_gridBlinkThread = New Thread(New ThreadStart(AddressOf GridBlinkThreadFunc))

_dataInputThread.IsBackground = True
_gridBlinkThread.IsBackground = True

_dataInputThread.Start()
_gridBlinkThread.Start()
End Sub

Private Sub DataInputThreadFunc()
Dim rand As New Random()
While True
If DataGridView1.IsDisposed Then
Exit While
End If

Dim data As New CellData()
data.Row = rand.[Next](0, 7)
data.Col = rand.[Next](0, 3)
data.Time = DateTime.Now

Dim value As Integer = rand.[Next](0, 101)

If InvokeRequired Then
DataGridView1.BeginInvoke(SetCell(data, value))
End If

SyncLock _blinkData
_blinkData.Add(data)
End SyncLock

Thread.Sleep(1000)
End While
End Sub

Private Function SetCell(ByRef Data As CellData, ByVal value As Integer)
DataGridView1.Rows(Data.Row).Cells(Data.Col).Value = value
DataGridView1.Rows(Data.Row).Cells(Data.Col).Style.BackColor = Color.Salmon
Return Nothing
End Function


Private Sub GridBlinkThreadFunc()
While True
' Make a copy to avoid invalid operation exception
' while iterating through the map
Dim tempBlinkData As List(Of CellData)
SyncLock _blinkData
tempBlinkData = New List(Of CellData)(_blinkData)
End SyncLock

For Each data As CellData In tempBlinkData
Dim elapsed As TimeSpan = DateTime.Now - data.Time
If elapsed.TotalMilliseconds > 500 Then
' 500 is the Blink delay
If DataGridView1.IsDisposed Then
Return
End If

If InvokeRequired Then
DataGridView1.BeginInvoke(ClearCell(data))
End If

SyncLock _blinkData
_blinkData.Remove(data)
End SyncLock
End If
Next

' Blink frequency
Thread.Sleep(250)
End While
End Sub

Private Function ClearCell(ByVal Data As CellData)
DataGridView1.Rows(Data.Row).Cells(Data.Col).Style.BackColor = DataGridView1.Columns(Data.Col).DefaultCellStyle.BackColor
Return Nothing
End Function

End Class
GeneralRe: VB.NET Version Here (Visual Studio 2005) Pin
Raghavan Ram Raja14-Oct-08 4:07
memberRaghavan Ram Raja14-Oct-08 4:07 
GeneralBlink Pin
txALI29-Jan-08 5:16
membertxALI29-Jan-08 5:16 
GeneralSome comments Pin
Kristof Verbiest10-Sep-07 21:16
memberKristof Verbiest10-Sep-07 21:16 
GeneralRe: Some comments Pin
Ram Mohan Raja11-Sep-07 5:42
memberRam Mohan Raja11-Sep-07 5:42 
GeneralRe: Some comments Pin
Kristof Verbiest11-Sep-07 22:11
memberKristof Verbiest11-Sep-07 22:11 
GeneralRe: Some comments Pin
Ram Mohan Raja12-Sep-07 5:46
memberRam Mohan Raja12-Sep-07 5:46 
GeneralRe: Some comments Pin
Kristof Verbiest12-Sep-07 22:06
memberKristof Verbiest12-Sep-07 22:06 
GeneralRe: Some comments Pin
Ram Mohan Raja13-Sep-07 5:05
memberRam Mohan Raja13-Sep-07 5:05 
GeneralRe: Some comments Pin
Kristof Verbiest13-Sep-07 5:40
memberKristof Verbiest13-Sep-07 5:40 
GeneralRe: Some comments [modified] Pin
Ram Mohan Raja13-Sep-07 6:40
memberRam Mohan Raja13-Sep-07 6:40 
GeneralRe: Some comments Pin
radioman.lt@gmail.com31-Oct-07 1:26
memberradioman.lt@gmail.com31-Oct-07 1:26 
GeneralRe: Some comments Pin
Ram Mohan Raja31-Oct-07 4:33
memberRam Mohan Raja31-Oct-07 4:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 4 May 2008
Article Copyright 2007 by Rammohan Raja
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid