This article provides a surprisingly efficient way of displaying real-time data changes in an Excel-style grid. When choosing to display data in a grid pattern, your natural first-choice would be to use a
DataGrid control bound to a
DataSet. However, I thought I'd try using a
ListView control for the same purpose.
The aim was to provide a lightweight control that requires very little memory and processing power and has very small latency under heavy load. The simple definition of latency is the time delay between the moment something is initiated and the moment its first effect begins. For software this is usually measured as the time between the raw data arriving and the results being displayed on the screen.
Q. Why does it matter how much processing power is being used?
A. Developing software for the financial sector isn't for the faint-hearted. Huge sums of money can be made or lost in a very short space of time and for the developer, this means that the software has to be reliable, robust and above all, very fast. One of the hallmarks of well-written financial software is very small latency.
The main cause of problems is due to the sheer volume of data that needs to be processed and analysed as quickly as possible; a corporate profit warning, an unexpected change in interest rates or a terrorist attack will all send a shockwave around the financial markets of the world and result in an overwhelming amount of data being generated. This is known in the trade as a 'Fast-Market'.
The data is usually received via data-streams from financial exchanges like Dow-Jones, Liffe and Eurex and this is an obvious case for multi-threaded processing being used to boost performance. However, the data also needs to be displayed in an informative way and this requires the use of a GUI - a notoriously single-threaded process. In poorly designed systems this can lead to a fatal bottleneck with the actual rendering of the data taking up far too much of the available processing power. The result will be out-of-date information being displayed to the user as current data is backed-up awaiting display.
If more processing power is being used by the GUI, it will mean that there's less processor available for the data analysis algorithms that are busy crunching data in the background.
The Example Application
The example application is a bit contrived but demonstrates a typical scenario for which a real-time data grid is required. A random data feeder is used to simulate market data arriving on multiple threads. The speed at which the data arrives can be controlled by using a sliding scale from 0 (No-Data) to 10 (Fast-Market). There are also a couple of buttons that will provide a sudden burst of data that will flood the grid with update events all at once, something that is quite common in the financial markets whenever key data is released.
The remaining controls are all concerned with the appearance of the grid itself and are meant to illustrate the effect on performance that the different painting effects have.
This article assumes a working knowledge of .NET programming with C# and a familiarity with the standard windows
ListView control. The control of interest is unimaginatively named
ActiveGrid and is little more than an owner-drawn
ListView control with the
View property hardwired to
ListView control, along with its Items and SubItems, have all been sub-classed so that some of the key functionality can be either intercepted or overridden. A more obvious candidate would be the
DataGrid control but for my money, the
ListView has always looked more appealing than a
DataGrid from an aesthetic point-of-view and this was my main reason for using it. It comes with some very useful built-in functionality and it would be a shame to lose this.
System.Windows.Forms Base Class
This class is responsible for the presentation of content in both the column header and all of the cells belonging to the column. In addition to all of the existing properties of the
System.Windows.Forms.ColumnHeader, a new category of properties has been created to handle the appearance of the cells:
This class is the main control that hosts the collections of both columns and rows. The
System.Windows.Forms.ListView class from which it is derived can be displayed in five different view-types but only the
Details setting makes any sense if you want to display a grid style view. Consequently, this property is hardwired in the derived class. Additional key properties are provided in two new categories:
This class is where most of the new functionality is to be found and mainly concerns the presentation of the cell contents. There are three text regions in every cell:
The centre text-string is aligned according to the
CellHorizontalAlignment setting in the column header. Each of the three text regions has its own user-defined colour, font and string. All aspects of the cell's appearance can be modified at run-time immediately prior to re-painting it. This enables individual cells to be color-coded according to the type of change being made. For example, if the value is increasing it can be drawn in blue, whereas if the value is decreasing it can be drawn in red.
- Columns can be moved at run-time
- Rows can be sorted by column by clicking on the column header
- The row header behaves like a
What is presented here is an alternative approach to the standard
DataGrid that could easily be used under the right circumstances. It's very efficient and can be easily extended to suit your own business requirements.
It also emphasises the relationship between GUI complexity and processor requirements. There is an ever increasing tendency to make software that is as good-looking as possible but unfortunately all of this 'sex-appeal' comes at a price. As a general rule, the more plain and boring your user interface, the better your performance will be. This is important to bear in mind if the processing power could be better used elsewhere. Of course, this can always be offset by better hardware. A top-of-the-range processor and graphics card will serve you well in this example, which is all very well if your budget can run to it. If it can't, you'll just have to rely on good, old-fashioned coding that gets the job done as efficiently as possible.
- 29 September 2007: Release 220.127.116.11 of