Almost any modern financial application that works in real time should be able to highlight dynamically changing data. This becomes especially important with continuous growth of data volumes and increasing market volatility. There are many examples of highlighting, e.g. change of cell background color for specified time on item price change or change of risks calculated in real time.

Highlighting of grid cells with quickly changing information requires understanding of the painting system in OS Windows and ability to maximize highlighting efficiency while minimizing consumption of CPU and memory resources.

To understand difficulties that may be encountered by programmers, let’s first look at the painting system in Windows. As you know, it is asynchronous. First, repainted area is defined with Control.Invalidate(Rectangle) method, and then Windows generates WM_PAINT message that directly performs repainting of cell content.

Now let’s see, what a programmer should do to correctly implement data highlighting system in a regular grid.

  • When a data cell needs to be highlighted for certain time, highlighting color should be stored (it will be required later, during painting). This requires a container storing the list of cells that are highlighted with certain color at certain time.
  • When highlighting begins, a cell of corresponding color should be placed into this container with information of required highlighting time.
  • Call Control.Invalidate(Rectangle) method for this cell. After that, Windows will generate a WM_PAINT message. Previously stored color should be used for the painting process.
  • When highlighting time expires, Control.Invalidate(Rectangle) method should be called again to return the cell to original state. A programmer should also store information of highlighting time for each cell and create a timer that calls cell repainting on timeout.
  • When multiple cells are highlighted simultaneously, the above timer should be shared between different cells that are currently highlighted. Shared use of timer is required to enable the most efficient use of computer resources as Windows OS supports a limited number of timers. A programmer has to enable continuous modification of timeout value since different cells have different time of highlighting expiration.
  • A programmer should also consider that a new request for highlighting of a cell with the same or different color may arrive for already highlighted cell. Therefore, this information has to be processed, while timeout and highlighting color have to be updated for the affected cell.
  • To save memory, container should be timely cleared of cells that are no longer highlighted.
  • It is also necessary to consider that a data row can be filtered, sorted or removed from the grid. Since this may happen when cells are highlighted, it is necessary to handle such situations or the application may crash.
  • For performance and CPU usage optimization, the highlighting system should work only with visible cells. If a user starts scrolling data vertically or horizontally, the program should track previously unseen cells showing in the visible area, determine remaining time of highlighting and call Control.Invalidate(Rectangle) method to highlight them as necessary.
  • There are also other issues that should be taken into account to improve display quality, performance and memory consumption. E.g., if a grid highlights cells with some rows selected, highlighting and selection colors should be mixed for a better perception.

We can see that data highlighting system in an application is fairly complicated, and it is not always possible to meet all requirements due to lack of time or experience in programming for Windows.

One of distinctive .Net Grid features is an integrated grid cell highlighting system that supports specified color for the specified period of time. This system implements all the above actions including control of timers and containers that store colors and timeout values for highlighted cells. The grid timely clears containers of unused data and on highlighting timeout. This system also calculates cell highlighting colors mixing them with colors of odd/even rows and with selection and focus colors.

All complex details of highlighting management is hidden inside the grid, while a programmer gets a simple API to control cell highlighting with specified color for specified period of time:

C# Copy imageCopy
Row row = ...;
Cell cell = row["Price"];

//Blink the background for 1 second
cell.Highlight(TimeSpan.FromMilliseconds(1000), Color.Green);

//Blink cell's foreground and backgroung for 500 milliseconds
cell.Highlight(TimeSpan.FromMilliseconds(500), Color.Green, Color.Red);

This approach enables simultaneous highlighting of multiple cells including cells outside visible area of the grid.

Cell highlighting and INotifyPropertyChanged

The grid supports automation of cell highlighting on notifications from data objects that implement INotifyPropertyChanged interface. Highlighting attributes such as colors, time interval and highlighting type are set with Grid.Highlighting property. On notification, the grid synchronizes call with GUI thread if required and then it calls Cell.Highlight()()()() with parameters taken from settings. Grid.RowUpdated event is the best way to control highlighting color and time. This event occurs on every notification from an object implementing INotifyPropertyChanged interface after synchronization with the main thread (if required). A Row containing the data object and IDataField with information of changed property are sent as arguments for this event. It is possible to add custom code to this event handler enabling highlighting of one or more cells with defined parameters.

C# Copy imageCopy
//Set default highlighting parameters
grid.Highlighting.Color = Color.Gold;
grid.Highlighting.Interval = TimeSpan.FromSeconds(2);
grid.Enabled = true;
grid.Highlighting.Fading = false;

//Highlight 'Price' cell green when the price goes up and red when reduced. 
grid.RowUpdated += delegate(object sender, GridRowUpdateEventArgs e)
{
    if(e.DataField.Id == "Price")
    {
        Share share = (Share) e.Row.DataObject;
        Color color = share.Price > share.PrevPrice ? Color.Green : Color.Red;

        //Highlight the cell with the selected color
        e.Row["Price"].Highlight(TimeSpan.FromMilliseconds(1000), color);

        //Highlights some other cell with other color when Share.Price is changed
        e.Row["OtherField"].Highlight(TimeSpan.FromMilliseconds(1000), Color.Orange);
    }
};

Cell highlighting is a continuous process. Cells can be repainted not just twice (before and after highlighting) but many more times within the specified time interval. This can be used to implement fading effect by multiple redrawing of cell background with changing transparency factor. When cells are redrawn, a programmer can always see how much time remains till the end of highlighting.

C# Copy imageCopy
grid.PaintCell += delegate(object sender, PaintCellEventArgs e)
{
    if(e.Cell.Column != null && e.Cell.Column.Id == "Price")
    {
        TimeSpan remainingTime = e.Cell.RemainingHighlightTime;    

        //Do a special painting here
    }
};

Highlighting control system enables efficient control of colors of different elements, mixing colors if necessary. E.g., it supports selected rows with highlighted cells. To enable this effect, the grid supports semi-transparent mode controlled by alpha factor set for selection and highlighting color.

C# Copy imageCopy
//Set semi-transparent selection
grid.Selection.Color = Color.FromArgb(50, Color.Blue);

//Highlight 'Price' cell green when the price goes up and red when reduced. 
grid.RowUpdated += delegate(object sender, GridRowUpdateEventArgs e)
{
    if(e.DataField.Id == "Price")
    {
        Share share = (Share) e.Row.DataObject;
        Color color = share.Price > share.PrevPrice ? Color.Green : Color.Red;

        //Add transparency:
        color = Color.FromArgb(80, color);

        //Highlight the cell with the selected color
        e.Row["Price"].Highlight(TimeSpan.FromMilliseconds(1000), color);
    }
};