Click here to Skip to main content
15,672,024 members
Articles / Programming Languages / C#
Posted 3 Sep 2007


83 bookmarked


Rate me:
Please Sign up or sign in to vote.
4.79/5 (13 votes)
3 Sep 20075 min read
A WinForms control for displaying time series diagrams.
Sample Image - maximum width is 600 pixels


The image seen above should be familiar to folks who have read, or glanced the cover of Edward Tufte's The Visual Display of Quantitative Information. It is a time series, showing the schedule of two routes of Santa Clara VTA's (Valley Transportation Authority) graphically. The image was generated by the first sample application (VTAView), which uses Timeline, a customizable, interactive, WinForms control that I wrote for displaying time series diagrams. Timeline can display static information known beforehand, like that of a timetable, as well as information that changes as time progresses.

ProcessMonitor, the second sample application, makes use of a timer and the Timeline control to create a dynamic time series diagram to show variation in resources used by a process across time. This article describes the design of the control and its usage in applications.


The implementation of Timeline is based on the idea of a time window showing a section of the total time (world time). The time window shows the visible portion of the total time and all operations like scrolling and zooming work on the time window. Data items are added to the time series by providing a data provider to the control. The control manages the display of data items, depending on the current time window. This design allows the world time to be potentially infinite and this allows creation of time series diagrams that dynamically add information as time progresses. The class diagram below shows the classes and interfaces in the control.

Timeline class diagram

The main class, Timeline, has the following properties:

  • OffsetTimelineFromAxis : This boolean property controls whether the time series is drawn inline or offset from the axis labels.

    TrueOffset True
    FalseOffset False

  • TimeScalePainter : Allows customized drawing of the timescale (at the top). The default implementation, DefaultTimeScalePainter, draws the timescale like this:

    Image 5.

    Consumers of the control can implement the ITimesScalePainter interface, or subclass DefaultTimeScalePainter, to customize the way it is drawn.

  • TimeZoneWidth : The width of a time zone (one division of the time scale).
  • ZoomFactors : The list of stepping factors to be used when zooming, in minutes. For example, setting this to {1.0/60, 1, 5, 15, 30, 60} results in the ability to zoom in until each time zone represents a second (1/60), and zoom out upto an hour, with the intermediate factors being 1, 5, 15 and 30 minutes. The current zoom factor controls how much time each timezone represents.

The methods in the control are:

  • AddDataProvider : This is the single most important method in the class, taking an implementation of the ITimelineDataProvider interface as its parameter. The data provider is responsible for adding data items to the time series.
  • MoveTimeWindowLeft : Moves the time window to the left. The overload without a parameter moves it left by one timezone, (the time represented by the time zone depends on the current zoom level), and the other overload moves it left by the specified number of minutes. Dragging the mouse across the control also moves the time window.
  • MoveTimeWindowRight : Moves the time window to the right. Dragging the mouse across the control also moves the time window.
  • SetInitialTimeWindow : Sets the time window's starting time and the zoom factor to be applied (or the ending time) when the control is initialized for the first time.
  • SetTotalTimeWindow : Sets the world start and end time. The time window cannot be moved outside the world time.
  • ZoomIn : Decrements the zoom factor index by one, resulting in each time zone representing a smaller unit of time.
  • ZoomOut : Increments the zoom factor index by one, resulting in each time zone representing a larger unit of time.


Using the control requires implementation of the following interfaces:


ITimelineDataItem represents one data item in the time series. Timeline gets a list of ITimelineDataItems from the data provider and renders them on the screen if they lie within the current time window. In the image shown at the beginning of the article, each stop is a data item and is given to the control as a TrainStopItem class, implementing the ITimelineDataItem interface. The interface has three getters:

  • Axis : returns the axis that this data item belongs to. In the sample image, each train station is an axis
  • ItemStartTime : returns the starting time of this item
  • ItemEndTime: returns the ending time of this item

It has one method, Draw, that implementors use to generate the visual representation of the item. Here's how TrainStopItem's Draw method is implemented:

public void Draw(System.Drawing.Graphics g, 
    TimeToXCoordinateDelegate timeToLocationConverter, float yStart, 
    float height, DateTime currentWindowStart, DateTime currentWindowEnd)
    float startX = timeToLocationConverter(start);
    float endX = timeToLocationConverter(end);

    float y = yStart + height / 2;

    using (Pen p = new Pen(Color.Red, 2))
        g.DrawLine(p, startX, y, endX, y);

    using (SolidBrush brush = new SolidBrush(Color.DarkGray))
        g.DrawString(this.end.ToString("HH:mm"), new Font("Calibri", 7), 
                new SolidBrush(Color.DarkGray), endX, y);

    if (nextStop != null)
        using (Pen p = new Pen(Color.Gray, 1))
            g.DrawLine(p, endX, y, timeToLocationConverter
                (nextStop.ItemStartTime), nextStop.Top);


This interface is used to provide information about the axes and data items to Timeline. The interface consists of two events, AxisFound and TimelineItemFound, that implementors can fire to inform the control about the discovery of a new axis or a data item. In the VTAView sample application, MainForm implements the interface and fires the events when loading the schedule from disk.

The reason why the data provider has events, instead of methods like GetAxes and GetTimelineItems, is that in certain kinds of applications using the control, the list of items and axis will not be available statically. The second sample application, ProcessMonitor, is a good example of those kinds of applications. ProcessMonitor shows dynamically changing parameters like processor usage and handle count for a process, and informing Timeline about new data points is best achieved through events.

Putting it all together

Here's a step by step guide to using the control in an application:

  1. Write classes implementing ITimelineItem to represent data items.
  2. Write one or more data provider classes implementing ITimelineDataProvider. Use the AxisFound event to return instances of IAxis derived classes and the TimelineItemFound event to provide instances of ITimelineItem derived classes to the control.
  3. Drag and drop the Timeline control onto a Form. In the Form class's InitializeComponent, use the SetTotalTimeWindow and SetInitialWindow methods to set the starting and ending times.
  4. Use the AddDataProvider method to link data providers created in (2) with Timeline.


  • Initial version - 8/26/2007


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Written By
Software Developer Atmel R&D India Pvt. Ltd.
India India
I'm a 27 yrs old developer working with Atmel R&D India Pvt. Ltd., Chennai. I'm currently working in C# and C++, but I've done some Java programming as well. I was a Microsoft MVP in Visual C# from 2007 to 2009.

You can read My Blog here. I've also done some open source software - please visit my website to know more.

Comments and Discussions

QuestionITimelineItem derived class clickable? Pin
Member 1384218425-May-18 2:06
Member 1384218425-May-18 2:06 
GeneralMy vote of 5 Pin
Member 35305349-Jul-16 17:47
Member 35305349-Jul-16 17:47 
Generalone of my stupid mistakes Pin
Prim00019-May-10 0:05
Prim00019-May-10 0:05 
GeneralRe: one of my stupid mistakes Pin
Prim00019-May-10 1:18
Prim00019-May-10 1:18 
GeneralPerformance Pin
Pedro3111-Sep-07 22:29
Pedro3111-Sep-07 22:29 
GeneralTimeline Class Diagram Pin
Armando Airo'3-Sep-07 20:53
Armando Airo'3-Sep-07 20:53 
GeneralRe: Timeline Class Diagram Pin
S. Senthil Kumar4-Sep-07 7:26
S. Senthil Kumar4-Sep-07 7:26 
My bad - fixed now. The submission wizard did not upload the image because it was more than 640 px wide.

Senthil [MVP - Visual C#]
My Blog | My Articles | My Flickr | WinMacro

GeneralGood control Pin
NormDroid3-Sep-07 20:42
professionalNormDroid3-Sep-07 20:42 
GeneralRe: Good control Pin
S. Senthil Kumar4-Sep-07 7:26
S. Senthil Kumar4-Sep-07 7:26 
GeneralRe: Good control Pin
| Muhammad Waqas Butt |4-Sep-07 23:41
professional| Muhammad Waqas Butt |4-Sep-07 23:41 

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.