Tutorial: Getting Started with Microsoft Chart Controls
Applies to: Functional Programming
Published: January 2010
Summary: This tutorial shows how to use the Microsoft Chart Controls library from F#. It explains how to create a chart, change its visual properties, and add another data series to the chart.
This topic contains the following sections.
- Using Chart Controls
- Displaying a Simple Column Chart
- Changing the Look of the Chart
- Adding a Second Data Series
- Displaying the Chart in 3D
- Additional Resources
- See Also
This article is associated with Real World Functional Programming: With Examples in F# and C# by Tomas Petricek with Jon Skeet from Manning Publications (ISBN 9781933988924, copyright Manning Publications 2009, all rights reserved). No part of these chapters may be reproduced, stored in a retrieval system, or transmitted in any form or by any means—electronic, electrostatic, mechanical, photocopying, recording, or otherwise—without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.
The Microsoft Chart Controls library is a part of .NET 4.0, but it can be also installed for .NET 3.5. It provides a wide range of chart types and numerous options for changing the look of charts. This tutorial looks at the basic concepts of Microsoft Chart Controls and it shows how to use the library to create a simple chart from F# Interactive. You’ll learn how to:
Use Microsoft Chart Controls from F# Interactive
Create a chart with data and change its visual properties
Combine a column chart and a line chart in a single chart area
Specify properties of the chart area and display the chart in 3D
Charts are constructed from a couple of key elements that represent parts of a chart such as the area or individual data lines. It is useful to understand the overall structure of a chart, because various properties and visual aspects have to be changed by modifying the right element of the chart. The following list enumerates the main components:
Chart Series—A series corresponds to a single data set that is displayed as some type of chart in the charting control. The series can be displayed as a line, bars and points, or for example box plots. Among other things, the Series object is used to configure whether values of the series should be displayed as labels or to change the color of bars or lines.
Plot Area—A chart series is drawn onto a plot area. The area has visual properties, such as background and color of a grid, as well as properties related to data, such as ranges of axes. It is possible to display multiple chart series in a single plot area (for example columns and a line).
Chart—The main object that has to be created represents chart as a whole. It can contain multiple independent plot areas and can contain other chart elements such as the title. A chart object is a Windows Forms or ASP.NET control (both versions are available) that can be embedded directly into the GUI.
To demonstrate the above concepts, the following section creates a chart with a single plot area and single data series displayed as a column chart.
The examples in this article will be written using F# Interactive. This means that the code will use Windows Forms-based version of the library. The first step is to load the .NET assembly with the charting library, which can be done using the #r directive. The following listing demonstrates this and then creates an instance of the Chart type and adds a single area using the ChartArea type. Finally, it adds the chart to a form and displays the form:
// Load Microsoft Chart Controls for Windows Forms #r "System.Windows.Forms.DataVisualization.dll" open System open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting // Create an instance of chart control and add main area let chart = new Chart(Dock = DockStyle.Fill) let area = new ChartArea("Main") chart.ChartAreas.Add(area) // Show the chart control on a top-most form let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500) mainForm.Controls.Add(chart)
The code that creates the Chart object specifies that the chart should fill the entire area of the form using the Dock property. Next, the snippet constructs a chart area and gives it a name that can be used later to look up the object in the chart.ChartAreas collection. When executed, the above listing should display a window with a blank (white) chart control on it.
The next step is to display some data on the chart. This is done by adding a series object to the chart. The following listing creates a Series with a default chart type, which is a column chart. Then, it adds 10 randomly generated values to the series:
// Create series and add it to the chart let seriesColumns = new Series("RandomColumns") chart.Series.Add(seriesColumns) // Add 10 random values to the series let rnd = new Random() for i in 0 .. 10 do seriesColumns.Points.Add(float(rnd.Next(100))) |> ignore
The Series type takes a name of the series (similarly to chart areas, it can be used to look up the series). Once it is created, the snippet adds the series to the main chart object. The series is added directly to the chart and the chart uses the default chart area to display it. In most of the cases, the chart contains just a single chart area. If it contained multiple areas, then the series can be associated with an area by setting its ChartArea property. The result of running the listing is shown in Figure 1.
The chart displays data in the required form, but it has a very basic design. The next section explains how to make it nicer.
The first change that can be done to improve the chart is to add a title. This is done by creating a new Title object and add it to the Titles collection of the main chart object (a chart can have multiple titles). The title is not needed later, so the following snippet specifies all its properties during object construction:
open System.Drawing // Add main title to the chart chart.Titles.Add (new Title( "Introducing Chart Controls", Font = new Font("Verdana", 14.0f)))
Running the snippet should add a title immediately on top of the chart. What other properties can be changed? Currently, the main chart area is just a grid of black lines. The following listing shows how to configure the background, change the color of grid lines, and configure other properties of the X and Y axes:
// Set gradient background of the chart area area.BackColor <- Color.White area.BackSecondaryColor <- Color.LightSteelBlue area.BackGradientStyle <- GradientStyle.DiagonalRight // Change appearance and range of axes area.AxisY.Maximum <- 110.0 area.AxisX.MajorGrid.LineColor <- Color.LightSlateGray area.AxisY.MajorGrid.LineColor <- Color.LightSlateGray
The first part of the snippet sets properties of the chart area. The properties can be also provided when creating the object using the syntax for specifying property values in a constructor call. The configuration above creates a diagonal gradient between two specified background colors.
The next part of the snippet is more interesting. The area object has properties that expose the main axes of the chart. In general, the chart can have multiple axes (see the area.Axes property), but most of the charts need just the two usual X and Y axes. The snippet first sets the range of the axis, which is done using Minimum and Maximum properties. Next, it also changes the color of the grid that is displayed behind the data series to a lighter gray color.
The next snippet does one more visual tweak by changing a couple of properties of the data series. The Series object has two kinds of properties. Those that are shared by all types of series are exposed as ordinary .NET properties. Properties that make sense only for certain types of charts are called custom properties and can be specified using an indexer:
// Specify common properties of the series seriesColumns.ChartType <- SeriesChartType.Column seriesColumns.IsValueShownAsLabel <- true // Specify custom properties of the column chart seriesColumns.["PointWidth"] <- "0.6" seriesColumns.["DrawingStyle"] <- "Cylinder"
The ChartType property configures the type of chart that is used to display the data series. This snippet modifies it just to demonstrate the property, because Column is the default value. There is a large number of other chart types available in the SeriesChartType enumeration. The IsValueShownAsLabel property specifies that the chart should include labels with the precise value of the displayed data.
The second half of the snippet sets two properties that are specific to bar charts and column charts. The PointWidth property specifies the size of the bar or column. The value 1.0 means that the columns should be placed directly next to each other. By setting the value to a smaller number, it is possible to add spaces between the columns or bars. The DrawingStyle property sets one of predefined visual appearances of columns. Other possible options include Emboss, LightToDark, and Wedge. The Cylinder option that was used in the snippet produces the chart displayed in Figure 2.
The next step of the tutorial adds a second data series to the same area of the chart. This can be used when comparing data or to show a larger amount of information in a single chart.
Multiple series can be displayed in a single chart by creating a new Series object and adding it to the chart. The second series can be of a different type, although some combinations are not allowed (for example, a column and a bar chart). The following snippet adds a line chart and specifies all its properties during the construction:
// Create new line chart data series let seriesLines = new Series("RandomLine", IsValueShownAsLabel = false, BorderWidth = 4, ChartType = SeriesChartType.Line) // Generate random values for the series for i in 0 .. 10 do seriesLines.Points.Add(float(rnd.Next(100))) |> ignore chart.Series.Add(seriesLines)
It is worth noting that custom properties of the series (that are set using the indexer syntax) cannot be specified in the constructor call. The previous listing didn’t need any custom properties. The snippet specifies the type of the chart (to a line chart) and hides the value labels. It also sets the thickness of the line, which is done using the BorderWidth property. Just like with the first series, the data is generated randomly.
Before looking at the result, the following section shows one more option of Microsoft Chart Controls. It is possible to display the whole chart in 3D to make it more attractive.
The 3D look of a chart can be enabled and configured using the Area3DStyle property of a series. One approach is to modify the individual properties exposed by the object representing the 3D style and another is to construct a new instance with the 3D properties and assign it to the Area3DStyle property. The following listing uses the second approach, which makes it possible to specify all of the properties using object construction syntax:
// Enable 3D look and rotate the chart area.Area3DStyle <- ChartArea3DStyle (Enable3D = true, IsRightAngleAxes = false, Rotation = 30, Inclination = 30, PointDepth = 100, PointGapDepth = 200)
Setting the Enable3D property to true tells the chart control to render the area in 3D. The remaining properties specify additional visual properties of the rendering. Disabling the right angle between the two axes enables more flexible rotating options, although this may make it harder to read information from the chart. Changing the Rotation and Inclination properties of the chart to the values from the snippet gives a chart shown in Figure 3.
As the screenshot shows, the data series that was added later (the line series) appears in front of the earlier series (the column series). The PointsGapDepth property can be used to specify the gap between the two series and the PointDepth property sets the depth of individual series.
This tutorial introduced the basic concepts of the Microsoft Chart Controls. A chart created using this library consists of chart areas and chart series. The demo created in this article started with a chart containing a single column series. Then, you saw how to combine multiple series (by adding a line chart). Finally, the example also demonstrated several options for changing the visual style of the chart.
This tutorial introduced the basic features of the Chart Controls library. The following articles discuss advanced topics such as data-binding and real-time data:
The sample in this tutorial uses the Chart Controls library directly using the types available in .NET 4.0. An alternative option is to use the FSharpChart library that builds on top of Chart Controls, but adds more F#-friendly API. For more information see the following articles:
To download the code snippets shown in this article, go to http://code.msdn.microsoft.com/Chapter-6-Visualizing-Data-c68a2296
This article is based on Real World Functional Programming: With Examples in F# and C#. Book chapters related to the content of this article are:
Book Chapter 4: “Exploring F# and .NET libraries by example” demonstrates how to create a simple charting application from scratch. This chapter is useful for learning F# programming when focusing on working with data.
Book Chapter 12: “Sequence expressions and alternative workflows” explains how to work with in-memory data sets in F# using sequence expressions and higher-order functions.
Book Chapter 13: “Asynchronous and data-driven programming” shows how to use asynchronous workflows to obtain data from the internet, how to convert data to a structured format, and how to chart it using Excel.
The following MSDN documents are related to the topic of this article:
Chart Controls is a MSDN section dedicated to working with Microsoft Chart Controls with many examples in C# and Visual Basic. It includes a comprehensive reference with all chart types and properties.
Chart Elements (Chart Controls) describes individual elements of a chart including chart area, series, axes and titles.
Constructors (F#) includes a discussion about the syntax allowing us to set values of settable properties when creating objects in F# using a constructor.