TeeChart for NET with MVC

TeeChart’s MVC & ASP.NET Charting options

For MVC, TeeChart for .NET can either render as a static image format such as PNG or JPEG or as a live javascript HTML5 Canvas object. See this page for some examples:
TeeChart MVC examples page. Some of the techniques used by TeeChart’s native ASP.NET Webform chart have been enabled for MVC. For further examples from ASP.NET see the full demo here: http://www.steema.net/TeeChartForNET/index.aspx.

This article concentrates on TeeChart’s implementation for MVC.

TeeChart for MVC

To create/call a Chart, from the view, we place have several options:

Render formats

Chart as an HTML5 canvas

The TeeChart may be rendered as an HTML5 Canvas coded by javascript. Steema provides a public Javascript Library that may be used at render time from NET projects to the webpage. TeeChart for .NET for the web extends capabilities across two possible programming environments, native .NET and Javascript. You can create a managed chart under the Visual Studio framework, within the controller and TeeChart will create the required Javascript to render the Chart (for MVC or ASP.NET) – plus – you can enhance the Javascript chart in virtually any way you desire by using javascript at the view or by generating it in the controller to render at the view. It’s your choice; we hope you like the flexibility it offers.

Chart as a static Image

Charts may be rendered as a static image, typical formats are PNG and JPEG.

Chart as a static Ajax enabled Image

Although this is a mode originally implemented for TeeChart’s Webform (ASP.NET) chart only, some of the techniques used may be extended for use in MVC. MVC can use the tools created for ASP.NET to generate clientside javascript for hotspot maps.

Call formats

Chart as an iframed live Javascript/HTML5 Chart

Example 1.
The first example uses an ActionResult to return a Chart. For these examples we’ve put several Chart routines in a Controller, here called “TeeChartMVCController”

The ActionResult does this:
public ActionResult GetHTML5Chart(int? number)
Steema.TeeChart.TChart wChart3 = new Steema.TeeChart.TChart();

if (number==0) //react to input variables
wChart3.Series.Add(new Steema.TeeChart.Styles.Pie());
wChart3.Series.Add(new Steema.TeeChart.Styles.Line());

wChart3.Series[0].FillSampleValues(); //data fill routines


We create the Chart according to the parameters received; in this case simply to choose between the type of Chart required. This is all native .NET code. You can build the Chart and render it to the page without the need to add any Javascript. The Chart export generates the required Javascript view code and links to TeeChart’s Javascript source. For this example we can and will add some Javascript though, to enhance features of the Chart on the page.

... continued

//optional - add in some custom javascript
//setting a clientside visualisation theme
string[] customCode = new string[] {" chart1.applyTheme(\"minimal\");" };
wChart3.Export.Image.JScript.CustomCode = customCode;

//setup the Chart export stream
tempStream2 = new System.IO.MemoryStream(); //create stream for transport
wChart3.Export.Image.JScript.Width = 800; //size the Chart
wChart3.Export.Image.JScript.Height = 300;
//build the Chart
wChart3.Export.Image.JScript.Save(tempStream2); //write to stream

tempStream2.Position = 0;
System.IO.StreamReader sr = new System.IO.StreamReader(tempStream2);

return Content(sr.ReadToEnd()); //return the Chart to the caller

This results in the following chart, well, nearly; the chart also includes a Tooltip, the description of which is covered in the next section:

Note. Examples on this page have been generated on a non-SSL server and cannot be viewed as frames here under SSL. If you can’t see the charts re-load page for non SSL (to view non-SSL demo charts)

ie. http://www.steema.net/TeeChartMVC/TeeChartMVC/GetHTML5Chart?number=2.

As an iframe this would be called in the following way from the page:

<iframe src=”http://www.steema.net/TeeChartMVC/TeeChartMVC/GetHTML5Chart?number=2″ width=”100%” height=”350″>

Example 2.
The second example shows how view code may be extended to use TeeChart’s Javascript Tools. This example, interpolation, brings together several elements to show how you can use cursor mobility with the chart to feedback information about its contents.

Note. Examples on this page have been generated on a non-SSL server and cannot be viewed as frames here under SSL. If you can’t see the charts re-load page for non SSL (to view non-SSL demo charts)

This is the controller code:
public ActionResult GetInterpolatedChart(int? type)

lock (renderLock)
Steema.TeeChart.TChart wChart3 = new Steema.TeeChart.TChart();

// wChart3.Export.Image.JScript.DoFullPage = false;

List<string> customCode = new List<string>();
List<string> externalCode = new List<string>();
List<string> externalHTML = new List<string>();

string[] externalHTMLS = new string[] {
"<font face=\"verdana\" size=1><span id=\"xpos\"></span><br/>",
"<span id=\"yposBar\"></span></font><br>"

string[] externalCodeS = new string[] {
" ",
" var posXLabel, posYLabel;",
" ",
" function interpolateLineSeries(s, xval) {",
" var yValues=s.data.values;",
" var len=yValues.length;",
" var xValues=[];",
" if (s.data.x)",
" xValues=s.data.x;",
" else {",
" for (i=0;i<len;i++)",
" xValues[i]=i;",
" }",
" var index;",
" for (index=0;index<len;index++) {",
" if (xValues[index]>xval)",
" break;",
" }",
" if (index<1)",
" index=1;",
" else",
" if (index>=len)",
" index=len-1;",
" var dx=xValues[index] - xValues[index-1];",
" var dy=yValues[index] - yValues[index-1];",
" if (dx!=0)",
" return dy*(xval - xValues[index-1])/dx + yValues[index-1];",
" else",
" return 0;",


string[] customCodeS = new string[] {
" ",
" ",

" var ypos=document.getElementById('yposBar'); ",
" for (i=0;i<3;i++) {",
" if (i>0) {",
" var br = document.createElement('br');",
" ypos.appendChild(br);",
" }",
" posYLabel=document.createElement('span');",
" posYLabel.id='ypos'+i;",
" ypos.appendChild(posYLabel);",
" }",

" ",
"tip=new Tee.ToolTip(chart1);",
"tip.domStyle = \"padding-left:8px; padding-right:8px; padding-top:2px; padding-bottom:4px; margin-left:5px; margin-top:0px; \";",
"tip.domStyle = tip.domStyle + \"background-color:#FCFCFC; border-radius:4px 4px; color:#FFF; \";",
"tip.domStyle = tip.domStyle + \"border-style:solid;border-color:#A3A3AF;border-width:1; z-index:1000;\";",
"tip.onhide=function() { scaling=0; poindex=-1; }",

"tip.ongettext=function( tool, text, series, index) { ",
" var s = '<font face=\"verdana\" color=\"black\" size=\"1\"><strong>'+ series.title+'</strong></font>';",
" s = s + '<br/><font face=\"verdana\" color=\"darkblue\" size=\"1\">Series point: <strong>'+ index.toFixed(0)+'</strong></font>';",
" s = s +'<br/><font face=\"verdana\" color=\"red\" size=\"1\">Value: '+series.data.values[index].toFixed(2)+'</font>'; ",
" return s;",
" ",

" var t=new Tee.CursorTool(chart1); ",
" t.direction='vertical';",
" t.format.stroke.size=1;",
" t.format.stroke.fill='gray';",
" chart1.tools.add(t);",
" var xValue;",
" ",
" posXLabel=document.getElementById('xpos'); ",
" t.onchange=function(p) {",
" xValue=chart1.axes.bottom.fromPos(p.x);",
" posXLabel.textContent='X Value = '+xValue.toFixed(2);",
" for (var i=0; i<chart1.series.items.length; i++){",
" posYLabel=document.getElementById('ypos'+i);",
" posYLabel.textContent=chart1.series.items[i].title+' Y Value = '+interpolateLineSeries(chart1.series.items[i],xValue).toFixed(2);",
" }",
" // changeTheme(chart1, 'minimal');",
" chart1.draw();",
" };",

"chart1.ondraw=function() {",
" var xs=this.axes.bottom.calc(xValue);",
" for (var i=0;i<this.series.items.length;i++) {",
" var ys=this.axes.left.calc(interpolateLineSeries(this.series.items[i],xValue));",
" var f=new Tee.Format(this);",
" f.fill=this.series.items[i].format.fill;",
" if ((!isNaN(xs)) && (!isNaN(ys)))",
" f.ellipse(xs,ys,8,8);",
" }",
" }",
" "

//"chart1.tools.items[0].setRender('layer'); chart1.draw();"

//********* end client code *********************


customCode.Add(" chart1.applyTheme(\"minimal\");");

Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line();
Steema.TeeChart.Styles.Line line2 = new Steema.TeeChart.Styles.Line();
Steema.TeeChart.Styles.Points p3 = new Steema.TeeChart.Styles.Points();

p3.Pointer.Gradient.Visible = false;

line1.Pointer.Visible = true;
line2.Pointer.Visible = true;

p3.Pointer.Style = Steema.TeeChart.Styles.PointerStyles.Circle;


wChart3.Legend.Visible = false;

for (int i = 0; i < 3; i++)

wChart3.Export.Image.JScript.CustomCode = customCode.ToArray();
wChart3.Export.Image.JScript.ExternalCode = externalCodeS.ToArray();
wChart3.Export.Image.JScript.BodyHTML = externalHTMLS.ToArray();

tempStream2 = new System.IO.MemoryStream();
wChart3.Export.Image.JScript.Width = 950;
wChart3.Export.Image.JScript.Height = 300;

tempStream2.Position = 0;

System.IO.StreamReader sr = new System.IO.StreamReader(tempStream2);

return Content(sr.ReadToEnd());

This is the view code:

<div class="col-md-5">
<iframe id="fr0" src="/TeeChartMVC/GetInterpolatedChart?number=2" style="border:none; width:970px; height:450px"></iframe>

This could be converted to an inline call. See the next section for details.

Chart as an inline live Javascript/HTML5 Chart

TeeChart’s Javascript Export class includes a property called DoFullPage. If set to “false” TeeChart hands you control to decide what elements to output to the page. TeeChart will create all of the code lines to generate the Chart but you’ll need to add the Canvas tag and the call to the Chart Draw method. This can of course be automated with your choice of naming convention. We’ve added an example to the TeeChartMVCController.

Note. Examples on this page have been generated on a non-SSL server and cannot be viewed as frames here under SSL. If you can’t see the charts re-load page for non SSL (to view non-SSL demo charts)

public ActionResult CreateInlineChart(int flag, int width, int height)
System.IO.MemoryStream ms = new System.IO.MemoryStream();

StringBuilder builder = new StringBuilder();

Steema.TeeChart.TChart wChart3 = new Steema.TeeChart.TChart();
Steema.TeeChart.Styles.Bubble bubble = new Steema.TeeChart.Styles.Bubble();
wChart3.Legend.Visible = false;
wChart3.Header.Visible = false;

Steema.TeeChart.Export.JavascriptFormat format = (Steema.TeeChart.Export.JavascriptFormat)(wChart3.Export.Image.JScript);

format.DoFullPage = false; //embedding code without headers

//name the related page elements
string ClientID = "w3";
format.CanvasName = ClientID + "img";
format.ChartName = ClientID + "_chart";

format.Width = width;
format.Height = height;

string[] customCodeS = new string[] {
" ",
" //tooltip",
" tip=new Tee.ToolTip("+format.ChartName+");",
" tip.render=\"dom\";",
" tip.domStyle = \"padding-left:8px; padding-right:8px; padding-top:2px; padding-bottom:4px; margin-left:5px; margin-top:0px; \";",
" tip.domStyle = tip.domStyle + \"background-color:#FCFCFC; border-radius:4px 4px; color:#FFF; \";",
" tip.domStyle = tip.domStyle + \"border-style:solid;border-color:#A3A3AF;border-width:1; z-index:1000;\";",
" "+format.ChartName+".tools.add(tip);",
" tip.onhide=function() { scaling=0; poindex=-1; }",

" tip.ongettext=function( tool, text, series, index) { ",
" var s = '<font face="verdana" color="black" size="1"><strong>'+ series.title+'</strong></font>';",
" s = s + '<br /><font face="verdana" color="darkblue" size="1">Series point: <strong>'+ index.toFixed(0)+'</strong></font>';",
" s = s +'<br /><font face="verdana" color="red" size="1">Value: '+series.data.values[index].toFixed(2)+'</font>'; ",
" return s;",
" }",
" ",
" "+format.ChartName+".applyTheme(\"minimal\");",
" ",

format.CustomCode = customCodeS.ToArray();

System.IO.MemoryStream chartImg = new System.IO.MemoryStream();


chartImg.Position = 0;
var sr = new System.IO.StreamReader(chartImg);
var javaScr = sr.ReadToEnd();

//add the source paths

//add our code block and load caller
builder.AppendLine(" window.onload = function(){ draww3() };");
builder.AppendLine("var " + format.ChartName + ";\r\nfunction draw" + ClientID.ToString() + "() {\r\n");

//add-in chart code


string styleStr = ""; //optional

//add the HTML5 canvas
builder.AppendLine(" 0 ? (styleStr + "\" ") : " style=\"\"")
+ " width=\"" + format.Width + "\" height=\"" + format.Height + "\">");

builder.AppendLine("\r\nThis browser does not seem to support HTML5 Canvas.");

return Content(builder.ToString());

The above chart generation routine is called from the MVC View in the following way:
@{ Html.RenderAction(“CreateInlineChart”, “TeeChartMVC”, new { flag = 2, width = 970, height = 400 }); }

Chart as an enhanced image

All TeeChart’s Chart types may be rendered as a static image in MVC. Some Ajax ‘enabling’ techniques may be borrowed from tools developed for TeeChart’s ASP.NET (Webform) version chart. In this example we’ll use the hotspot tool to generate a mouseover hint HTML map for the Chart. The technique may extended to offer inline or click-back drill down.


Note. Examples on this page have been generated on a non-SSL server and cannot be viewed as frames here under SSL. If you can’t see the charts re-load page for non SSL (to view non-SSL demo charts)

<img usemap="#MAPWebChart1" id="Chartimg3" src="/TeeChartMVC/GetStaticBarChart?w=950&h=350&image=true" style="border:none; width:970px; height:350px">
@{ Html.RenderAction("GetStaticBarChart", "TeeChartMVC", new { w = 950, h = 350, image = false }); }

The RenderAction calls the chart generation function generating the map only.

TeeChart for .NET Gauge demo – Subaru BRZ acceleration simulation

The example uses TeeChart’s Circular and Numeric Gauges to simulate the acceleration of a 2016 Subaru BRZ car.

TeeChart for NET Gauges. Subaru BRZ simulation

Example code for this demo may be downloaded from the github repository:

Demo code at github.com/Steema

This is a simulation only and though the basis is fairly faithful to empirical results it does not make claims to authenticity.

To compile this demo you need the TeeChart assembly, teechart.dll. The evaluation version can be downloaded via the evaluation version page:


Project notes

Some factors that the demo takes into account:
– Redline (change gear when reaching the redline)
– Powerband; keep the engine in the powerband after the changeup
– True top speed. The demo is close to reported performance data

For this demo not all the of gaugeable data has been put into TeeChart Gauge format, the fuel gauge and oil temperature gauge have been left alone, but they could also be automated.

The demo uses an image of a dashboard and superimposes TeeChart’s circular gauges on it. One of the dials has been remade from scratch and the other uses the existing scale.

Setting up the demo

This has been built as a winform demo.
An image of the dashboard is selected and modified to make the backdrop image of our working Form. The image has been prepared, removing the scale from the tachometer and the removing the dial needles from both the tachometer and speedometer.

Adding the Charts

The Tachometer is formed by one TeeChart and has been modified to use three TeeChart Series, a CircularGauge for the tachometer itself, one Numeric Gauge for the speed and another NumericGauge for the odometer and gear indicator.

The Speedometer is formed by a TeeChart CircularGauge.

Customising the TeeChart Gauges


The tacho scale has been completely rebuilt by the TeeChart Editor and some runtime code modifications. It reflects the original scale minus the redline zone, that, whilst it could be defined by TeeChart itself, remains part of the background image.

Gearchange indicator, digital-readout speed and distance covered are all included in two NumericGauges in the TeeChart “RevChart”.


The speedometer is limited to using a CircularGauge needle. The Gauge’s scale remains that of the underlying image.

Demo code

Data arrays

The demo is controlled by three arrays:

speedRevChgUp = new double[] { 39, 57, 86, 110, 133, 143 };
secsToChange = new int[] { 3, 3, 4, 6, 6, 10, 20 };
//gearchanges made at approx 7500rpm
speedRevDropStart = new double[] { 800, 4700, 5400, 5700, 6100, 5600 };

The rev limit for which to change gear has been defined at 7500rpm. The secsToChange array defines the time through each gear and the speedRevDropStart array, the revs to drop down to after a gear change. The speedRevChgUp array sets the top speed in each gear.


The demo form contains a Timer that is activated to run the simulation.
Control of the gears, speed, revs, distance and over-rev warning light are all controlled when the timer triggers.

Animated Activity Gauge with TeeChart Pro VCL

At the moment TeeChart Pro for VCL / FMX does not have a Series type available to create Activity Gauges, maybe in the near future, but here I will show how using another series type and some tricks we can create this kind of Chart.

The series type to use is the Donut series. We’ve to add as many Donut series as Activities we want on our chart.

I’m going to take advantage of the ease with which we can ask the TChart component to setup most of the steps at designtime, right from the Chart editor itself.

Once we have the Chart in the form and have added the different Donut Series, it doesn’t seem possible to get the desired result, but we’ll see…
The first thing to do is set the Chart to 2D, hide the Title and the Legend, we’ll also hide the Marks for each of the series. Here we have :

Now, it’s time to modify one of the important properties that will start to make changes. It’s the property named “Multiple Pies”, within the Editor -> Series -> Series1 -> Donut -> Options -> Multiple Pies. By default this is set to “Automatic”, we’ll change it to “Disable” for all of the Series.

Once this property is modified, it will look like we only have one Donut series in the Chart, as shown here.

It is time to change another important property that will modify the Chart, it is the property named “Hole%”, we find it within the options of each series, in the “Format” tab. Here we’ve to set different percentage values for each of the Donut series’ holes, distributing the size between the different Series. The first Series must contain smaller hole size, we can set a value of “60%”, in the second Series (in the case we’ve three series) we’ll set a value of “74%” and “88%” for the third. The result will be:

Now, all you have to do is hide the Pen for each Series, or set a different color and size, and we’ll have the look of the Chart that we wanted.


As an extra characteristic of the Series or Chart, I’m going to add a Text, just in the centre, that will show the activities value. To do this, I can use an “Annotation Tool” already available in TeeChart, and also created/added via the TChart editor. Set annotation alignment to “center” and format the font.

An important feature of this Series type (Activity Gauge) it’s its animation. TeeChart Pro incorporates several Animations for the different Series types, but in this case, as we’re creating a type of series totally personalized, we will create the animation manually.

We’ve to add three TTimer objects to the form, one for each series, set them “Enabled” to False and define an “Interval” of 10.

We can also add a Button component, which is the one that we’ll use to start the animation.

Now let’s give it functionality; we’ll do the next steps through code.

The first thing we do via code, is create a method where we’ll reset and initialize all the Series values, named “ResetValues”, this will be the code:

procedure TActivityGaugeForm.ResetValues;

var i : integer;
  ChartTool1.Text := '0 %';
  Chart1.Hover.Visible := false;

  for i := 0 to Chart1.SeriesCount-1 do
    Chart1[i].YValue[0] := 100;
    Chart1[i].YValue[1] := 0;
    Chart1[i].ValueColor[0] := Series1.Pen.Color;

We’ll call this method from the CreateForm event of Application, and also every time Button1 is clicked :

procedure TActivityGaugeForm.FormCreate(Sender: TObject);

procedure TActivityGaugeForm.Button1Click(Sender: TObject);
  Timer1.Enabled := true;
  Button1.Enabled := false;

Now, the only missing thing is to add the code that generates the Series animation inside its corresponding Timer event :

procedure TActivityGaugeForm.Timer1Timer(Sender: TObject);
  Series1.YValue[0] := Series1.YValue[0]-1;
  Series1.YValue[1] := Series1.YValue[1]+1;

  ChartTool1.Text := round(Series1.YValue[1]).ToString() + ' %';

  if (Series1.YValue[1] = 90) then
    Timer1.Enabled := false;
    Timer2.Enabled := true;

procedure TActivityGaugeForm.Timer2Timer(Sender: TObject);
  Series2.YValue[0] := Series2.YValue[0]-1;
  Series2.YValue[1] := Series2.YValue[1]+1;

  ChartTool1.Text := round(Series2.YValue[1]).ToString() + ' %';

  if (Series2.YValue[1] = 75) then
    Timer2.Enabled := false;
    Timer3.Enabled := true;

procedure TActivityGaugeForm.Timer3Timer(Sender: TObject);
  Series3.YValue[0] := Series3.YValue[0]-1;
  Series3.YValue[1] := Series3.YValue[1]+1;

  ChartTool1.Text := round(Series3.YValue[1]).ToString() + ' %';

  if (Series3.YValue[1] = 60) then
    Timer3.Enabled := false;
    Button1.Enabled := true;

We have everything. Now it’s time to run the application and see the result. You should see something similar to:


Source code of the example available at the Steema Github.


Linking Charts Demo – Connecting TeeChart for NET to data binding sources

This demo shows how TeeChart’s Charts can be made to work with each other on a Form in a Winform application.

The demo uses the basis of the company data of a small technical products supplier; the company sells electronic based products, small computers, tablets and mobile phones and has markets in some countries around the globe.

Demo code project, written with Visual Studio 2015, can be downloaded here: https://www.steema.com/files/public/teechart/net/LinkingCharts_TChartNET.zip. Version on Github here: https://github.com/Steema/TeeChart-for-.NET-CSharp-WinForms-samples/tree/master/LinkingCharts

Create the project

We create a new Winforms project, and rename the main form to ReportForm.
1. Add objects to Form. We add three charts, a dataGridView and a textbox to the form and position them to take up the full space of the form (see fig. 1).

Fig.1 Designtime in Visual Studio

2. Using the Chart Editor, we have added a dataseries to the charts plus a smoothing function that you can see populated with random data at this stage. Data series can be added at designtime or at runtime.
3. We’ve placed the company sales data in an MS Access file called TechProducts Ltd and placed the file in the LinkingCharts solution folder.

Add the data to the project

4. We’ve added the database to the project, publicising tables and queries (views).
5. Using BindingSource components we connect to the Access database. The database already has prepared queries for some of the data we wish to visualise. For other cases, during runtime execution, we will write some sql queries in the code.

Three BindingSources are added, connecting to the $_€_SalesByYear, $_SalesByCountry_2015 and $_SalesByContinent views.

Connect the Charts to the data

6. To connect to a bindingSource, open up the Chart Editor that you wish to modify and select the Series that has previously been added and go to its Datasource tab. If you click on the Dataset tab you can select the bindingSource to which to connect that Series. In the following selection boxes, you can relate the different source fields to the X and Y series valuelists. See Fig. 2.

Fig.2 Series datasource editor

7. Repeat the connection technique for the three charts. We have connected the left Bar Series Chart to the SalesByContinent data, the right, Pie chart, to the SalesByCountry_2015 data and the lower line chart to the SaleByYear data.

Linking the Charts

8. We now have three charts, data by continent, region (countries with sales, within a continent) and country. Our aim in this demo is to link the three chart so that, by actioning a click on a bar of the continent chart, we can fill the region chart and that by actioning a click on the region chart we can show the sales evolution, over the last few years, of the selected country. The dataGridView will update to show the contents of the region chart. Note that the demo will open showing all countries in the region chart. The textbox updates to show ‘simulation’ commentary by a “robot journalist”.

9. To link the different elements of the project page we’ll set up some chart events.

ClickSeries event
We are using the ClickSeries event to take the value from the clicked chart as argument in a query to populate the next, related chart.
We can add the event definition at designtime by selecting the chart from which we wish to action and selecting the events tab of Visual Studio’s Properties window and, in this case, selecting the click event from the list for the TChart. That creates the event method in the Form’s code page. Here we’ll need to add some content so relate the Series click with where we wish to go.
We have chosen to partially manually code the query for clarity. The method follows these steps:
Take the original query for the country/continent chart as the basis, modify it to collect data for all available years.

Modify region query:
@contiparam is the continent that you wish to view, sourced from the label of the Continents Chart value. One could use the index value or some other variable if that were to make a better index for the query.

string sqlStr = "SELECT Sum(Fact_Invoices.Invoice_Value) AS SumOfInvoice_Value, Lookup_Country.Country_name, Lookup_Continent.continent_name";
 sqlStr += " FROM((Fact_Invoices INNER JOIN Lookup_Customers ON Fact_Invoices.Cod_Customer = Lookup_Customers.Cod_Customer)";
 sqlStr += " INNER JOIN Lookup_Country ON Lookup_Customers.Country_code_A2 = Lookup_Country.Country_code_A2)";
 sqlStr += " INNER JOIN Lookup_Continent ON Lookup_Country.Continent = Lookup_Continent.continent";
 sqlStr += " where Lookup_Continent.continent_name = @contiParam GROUP BY Lookup_Country.Country_name, Lookup_Continent.continent_name";

DataSet customers = new DataSet();

System.Data.OleDb.OleDbDataAdapter myAdapter = new System.Data.OleDb.OleDbDataAdapter(sqlStr, this.___SalesByCountry_2015TableAdapter.Connection);

Modify country query:
We take the label of the country that we wish to review, as the argument for the country-over-time query.

string sqlStr = "SELECT Sum(Fact_Invoices.Invoice_Value)AS SumOfInvoice_Value, Fact_Invoices.Invoice_year AS AYear, Lookup_Country.Country_name";
sqlStr += " FROM(Lookup_Customers INNER JOIN Fact_Invoices ON Lookup_Customers.Cod_Customer = Fact_Invoices.Cod_Customer)";
sqlStr += " INNER JOIN Lookup_Country ON Lookup_Customers.Country_code_A2 = Lookup_Country.Country_code_A2";
sqlStr += " WHERE Lookup_Country.Country_name = @countryParam";
sqlStr += " GROUP BY Fact_Invoices.Invoice_year, Lookup_Country.Country_name";

Those queries are enough to link the charts. We have taken a click in the same way from the GridView. Taking just one of them as an example, for the region chart, you can see how a bindingSource is created for the recipient chart to ‘plug-into’.

Creating and using a new bindingSource with the sql query as source for Grid and Chart.

DataSet customers = new DataSet();

System.Data.OleDb.OleDbDataAdapter myAdapter = new System.Data.OleDb.OleDbDataAdapter(sqlStr, this.___SalesByCountry_2015TableAdapter.Connection);

//apply region code
myAdapter.SelectCommand.Parameters.Insert(0, new System.Data.OleDb.OleDbParameter("contiParam", region));
myAdapter.Fill(customers, "Customers");

bindEurope = new BindingSource();
bindEurope.DataSource = customers;
bindEurope.DataMember = customers.Tables[0].ToString();

dataGridView1.DataSource = bindEurope;

dataGridView1.Columns[0].HeaderText = "Sales Income";
dataGridView1.Columns[1].HeaderText = "Country";
dataGridView1.Columns[2].HeaderText = "Continent";

tChart3[0].DataSource = bindEurope;
tChart3[0].YValues.DataMember = "SumOfInvoice_Value";
tChart3[0].LabelMember = "Country_name";


The Chart Series’ CheckDatasource() method is used by TeeChart to refresh the Chart data.

Application output

The screenshots in Fig 3 & 4 show the application at runtime.

Fig. 3. Application startup

Fig. 4. Europe & Switzerland selected.

Creating Gauge Visualizations with TeeChart Pro VCL / FMX in your Applications

Gauges are increasingly used in our applications. Their capability to show different data sets, whether static or moving over time, makes gauges a valuable chart for dashboards or any other application which visually represents data.


First impressions count, and it’s important to understand data at a quick glance. For this reason dashboards are on the up and becoming increasingly more prevalent in modern data applications, hence we are seeing the many different types of gauges playing a vital role in dashboard design.


In this blog article, we’re going to look at the possibilities that TeeChart VCL/FMX offer us to simplify and speed up the creation of this type of data visualisation.


TeeChart Pro for VCL and FireMonkey include numerous professional chart styles, amongst which we find a wide range of gauges. It’s easy to start adding gauges to your Apps with the TeeChart components library. We can create the panel or dashboard we are referring to without the need to write a single line of code, and what’s more we can do so for all platforms supported by Embarcadero, making it an important cross-platform tool.


Note that all the functionality contained in the TeeChart Pro library of components is cross-platform compatible.


To begin with, let’s take a look at all the gauge types available with TeeChart Pro:



If we create a new application, display its form and add a TeeChart Chart to it from the component library, we can then double-click on the Chart to open the Chart Editor. From here we can add Series to the Chart and personalise them to our taste, all at designtime. To add a new Gauge Series we select ‘Add’ from the ‘Series’ section and go to the Gauges tab in the gallery that has opened, as you can see in Image 1.

Types of Gauges:

Numeric Gauge Linear Gauge Vertical Gauge


Circular Gauge Knob Gauge Clock Gauge

Each Gauge type has its own characteristics and functionality.

In this example, we’re going to add as many charts as there are gauge types available and we’ll change the appearance of each one of them via each of their respective editors.


TeeChart allows us to personalise each Series from the Object Inspector (and in VCL also from its own Editor dialogue).




We can download the demo from the Steema area on GitHub:

Using Gauges sample at GitHub


Using TeeChart we can always create any type of Gauge or Chart personalised to our requirements, that being because the TeeChart Canvas allows us to paint any object on it.

For example, if what we want is to create a type of Gauge of the style ‘Radial Gauge’ we can easily create it via a Donut Series. We’ll simply need to set a total angle (for example, 180º), position the Donut in the centre of the Chart via the 3D editor tab (using horizontal and vertical offset), adding an annotation tool in the centre for the dynamic percentage information.


Having done that, it’s only left for us to add values to the Series (for example 15 and 85). The result being:

Get more info and download the latest TeeChart Pro for VCL and FMX version at :



2x TeeChart speed in Firemonkey (FastLine, Direct2D)

The Firemonkey Canvas is fast but there is a performance problem when drawing lots of elements (“lots” being in the order of tens of thousands).

Using a TPath, adding all the elements to it and then drawing the TPath gives some speed gains but it is not enough. Time is lost filling the TPath anyway.

If the elements are simple lines, graphical apis like Direct2D or GDI+ have optimized shortcuts that run much quicker than drawing single lines many times.

Using simple rtti “hacks”, TeeChart “FastLine” series style is now twice as fast when there are a lot of points to display.

The gains are aprox 2x (twice the speed). It all depends on the combination of cpu + gpu + chart size + number of points.

This improvement will be included in the next coming update release.

There are some conditions to use this fast technique:

// All points in the series are painted as one big line, instead of multiple segments
Series1.DrawStyle := TFastLineDrawStyle.flAll;

// “null” (empty) values, if they exist, should be ignored (no gaps in the line)
Series1.TreatNulls := TTreatNullsStyle.tnIgnore;

// Tell canvas to use faster speed:
Series1.FastPen := True;


Performance gain, from 19 frames-per-second to 38:


The picture above shows 2 FastLine series, with 100.000 points each running on Windows.


GPU Canvas:

Unfortunately, there is no shortcut for a similar method in the TCanvasGpu (used on Android and iOS platforms).

Trying to simplify the StrokeBuild and FillTriangles methods for this case (lots of lines) gives only aprox a 10% speed improvement.


About reducing the number of points:

Its clear it is better not to add that quantity of points to the series, as there are not enough pixels to display them, but in some applications (specially when the data comes more or less in realtime) reducing the number of points can cost more time depending on the algorithm.

FastLine provides a basic point-reducer mechanism using a property:

Series1.DrawAllPoints := False;
Series1.DrawAllPointsStyle := TDrawAllPointsStyle.daFirst; // use first Y for all common X

And also :  “daMinMax” to draw vertical lines for points with repeated “X” coordinates.

TeeChart Pro version includes more advanced ways to do data-reducing at the TeeDownSampling.pas unit.

A TDownSamplingFunction can be used at design-time or run-time using several algorithms (including Douglas-Peucker Polygon Simplification) :

TDownSampleMethod=(dsDouglas, dsMax, dsMin, dsMinMax, dsAverage,dsMinMaxFirstLast, dsMinMaxFirstLastNull);

TeeFunction1.DownSampleMethod := TDownSampleMethod.dsDouglas;

Series2.FunctionType := TeeFunction1;  // <– Series2 will contain the “reduced” data
Series2.DataSource := Series1;  // <– Series1 has many points


RAD Studio 10.1 Berlin, add TeeChart to “FireUI Live Preview”

Studio 10.1 Berlin has just been released and includes the FireUI Live Preview tool to visualize forms at design-time in mobile devices and desktop (Windows / Mac OSX) machines.


The default application does not provide support for TeeChart control, but its very easy to add !

  • Open the LivePreview.dproj project in Studio 10.1 from:  c:\Program Files (x86)\Embarcadero\Studio\18.0\source\Tools\FireUIAppPreview
  • Edit the project’s Regs.pas unit to add the TeeChart related units (see code below)
  • Run the app (without debugging)
  • Create a new Firemonkey project, add a TChart control to see it at Live Preview (connect to your ide machine first)

There is only a minor caveat that should be easy to solve:

When adding series of data to TChart, they appear filled with random points at design-time.
However, Live Preview displays component contents without the “csDesigning” ComponentState property so the series appear empty.

Modifications to Regs.pas unit (displayed in bold font) :

unit Regs;


  System.Classes, FMX.Controls, FMX.ImgList,


  {$IF TeeMsg_TeeChartPalette='TeeChart'}

  FMXTee.Editor.Pro,  // <-- if you have the Pro version of TeeChart

  FMXTee.Chart, FMXTee.Series;



  // Register here any component that is not previously registered by the framework




Introducing TeeChart XAML

We’re excited to introduce you yet another addition to our TeeChart .NET line of products.

This time, we’re focusing on comfort and ease of use for programmers. While TeeChart for WinForms presents the programmers with a fully-featured designer, the visual support in other platforms is more lacking. I’m referring to what we call the XAML platforms: WPF, Silverlight, UWP and Xamarin.Forms.

In order to solve this usability problem, we’re making TeeChart and XAML understand each other better. Until now, if you wanted to design a chart using one of these XAML platforms, you had to place all the code to configure it by hand in the code-behind. Now, you will be able to build your charts with XAML code, as well as using the Visual Studio Designer for XAML.

We’re also introducing bindings to pretty much every property of your charts, thus enabling support for MVVM-oriented workflows. You will be able to tell the chart to grab your data from, for example, an ObservableCollection, and it will even update the series when the collection changes.

This will also bring support for Styles to your charts. Being able to set the font and background for all the charts in your window in a single declaration has never been easier!

Once TeeChart and XAML understand each other, the Visual Studio designer will be able to edit most of the properties out of the box. However, we’re not satisfied with that, and we’ll bring custom editors and designers to extend the Visual Studio designer’s functionality.

Here’s a sneak peek of what’s to come (click the image to enlarge):


Keep in tune for new announcements and details soon, including a Beta for interested clients!

Big files: XML or JSON ? TeeBI !!

TeeBI Dashboards



XML and JSON are very typical text formats used to store data, designed to be more comfortable than plain old “csv” text and allowing hierarchical (parent -> child) relationships.

However, even if there are many wonderful standard libraries to process them, there is still a speed problem when loading big quantities of data (say, hundreds or thousands of megabytes).

Content has to be parsed and stored into memory structures representing the “tree” nature of data nodes and attributes, which can be very fast (milliseconds) for small files, but terribly slow (minutes !) for big ones.

TeeBI core base class (TDataItem) is an “agnostic” memory structure providing parent -> child connections, using simple arrays to store data (one array per field or column).


TDataItem = class
Name : String;
Items : Array of TDataItem;   // <--- Children
Kind : TDataKind;  // <-- Integer, String, Float, DateTime, Boolean, or "List of TDataItem"
Data : Array of ...    //  <--  one array for each Kind: "Int32Data : Array of Int32"


With a TDataItem, loading and saving big quantities of data is insanely fast (0.2 seconds to load or save 1 million rows with 4 columns on a normal PC).

The arrays are saved / loaded to / from Streams directly in one Write / Read operation.

That means we can import data from XML or JSON (or any other format like database datasets, server connections, Excel, etc, etc) into a TDataItem and then save it to a binary TeeBI file for later reuse.

Data := TDataItemPersistence.Load( 'my data.bi ')


Once a TDataItem is created or loaded, we can use it in many ways:

  • Search and modify data, re-structure columns
  • Sort data by multiple fields, and by custom expressions
  • Run ultra-fast SQL-like queries and summaries against TDataItems
  • Set master -> detail relationships between different TDataItems
  • Filter rows by code or using expressions (as strings or as TExpression classes)
  • Create calculated columns (using code or expressions)
  • Merge several TDataItems
  • Compare the structure and / or full data of TDataItems to obtain difference sets
  • Present TDataItems using Grids, Charts, Dashboards and PDF output
  • Connect TDataItems to a super-fast TBIDataset (a normal memory TDataset class)
  • Export to any other format (for example XML to JSON and vice-versa)
  • Access remote TDataItems from web servers transparently
  • Apply machine-learning algorithms using R or Python Scikit-learn
  • Access basic statistics of any TDataItem or child item


Note to TeeChart developers:

TeeBI includes a new TBIChart control (derived from TChart) that is capable of automatically creating new chart series and fill them from any TDataItem.

BIChart1.Data := MyDataItem;

A planned new feature is to integrate the Data property editor dialog inside the normal TeeChart editor, for design-time support (zero code charting !)


TeeBI library is available for download at the following link:


Supported development environments:

  • Embarcadero Studio (Delphi, C++) from XE4 version and up
  • Lazarus FreePascal
  • …and soon for Microsoft Visual Studio .NET

Several 3rd party products can be optionally used with TeeBI:



For more information:

Please visit the TeeBI community at Google+ and the TeeBI home website for more information and technical details.



Connecting TeeChart to MySQL at design/run-time on C# .NET Winforms


Connecting a TeeChart control to MySQL database at design-time using the TeeChart Editor and at run-time.

The sourcecode for this demo is available via this github resource:


It assumes that you have a later version of TeeChart for .NET installed in your machine. You can use a TeeChart evaluation version if you don’t have the registered version to hand. See this page: https://www.steema.com/downloads/net


Example 1. Connecting to MySQL at design-time

MySQL Driver

  1. Download and install the MySQL Driver from https://dev.mysql.com/downloads/connector/odbc/
  2. Add the OdbcConnection and the OdbcDataAdaptar to the ToolBox.


  1. Create a new user or system data source using ODBC Data Sources (32bits/64bits).



  1. Drag an OdbcDataAdapter onto a WinForm with a TeeChart for .NET object on it. Add a New Connection on the Data Adapter Configuration Wizard.



  1. Now click on the “Query Builder” button and add in the “usastates” Table. Close the “Add Table” window and select the “*(All Columns)” CheckBox:


  1. Click “Ok”, “Next” and “Finish”.


  1. Assuming you have placed a TeeChart on a form, now open the TeeChart Editor and add a new Series.


  1. Click on the “Series” tab and choose the data that you wish to plot. In this case, select “Database”, choose the Dataset previously created and select the data that you want to use.


  1. Click “Apply”. You should now have something like the following in the design-time:




  1. Add the following line of code to apply the changes in design-time of the chart when you execute the form:




This demo has loaded data into a TeeChart Bar Series as a test exercise. The data plotted in this way generated a simple chart based on Perimeter values for states in the USA. Whilst the exercise has been of interest as a generic exercise, the datasource content itself leads us on to the second exercise which will use the data from the source in a more suitable manner. The data is ESRI shapefile map data and for the second exercise we’ll plot it as a map.




Example 2. Connecting TeeChart to a MySQL datasource at runtime


For this part of the exercise we’ll use an ESRI shape file to load a world map into TeeChart. TeeChart already has its own map resources so loading this map isn’t strictly necessary to be able to view a World Map series, but as the ESRI shapefile format is widely used (see this document for some specification details: https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf) the example may be useful to help you to plot your own shapefile data.


  1. Select the TChart component from the Toolbox and drag it onto your form.


  1. Select an ODBCAdapter component and an ODBCConnection component and place them on your form. You can use the component wizards to connect to you datasource. For the purpsoses of our exercise it will generate code similar to the following code:


// odbcDataAdapter1
this.odbcDataAdapter1.SelectCommand = this.odbcSelectCommand1;
this.odbcDataAdapter1.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] {
new System.Data.Common.DataTableMapping("Table", "Table", new System.Data.Common.DataColumnMapping[] {
new System.Data.Common.DataColumnMapping("CODE", "CODE"),
new System.Data.Common.DataColumnMapping("CNTRY_NAME", "CNTRY_NAME"),
new System.Data.Common.DataColumnMapping("POP_CNTRY", "POP_CNTRY"),
new System.Data.Common.DataColumnMapping("CURR_TYPE", "CURR_TYPE"),
new System.Data.Common.DataColumnMapping("CURR_CODE", "CURR_CODE"),
new System.Data.Common.DataColumnMapping("FIPS", "FIPS")})});
// odbcSelectCommand1
this.odbcSelectCommand1.CommandText = "SELECT   world.*\r\nFROM       world";
this.odbcSelectCommand1.Connection = this.odbcConnection1;
// odbcConnection1
this.odbcConnection1.ConnectionString = "Dsn=world_map;uid=flute_16_r;";

We have used a test database configured on a MySQL server at db154.pair.com:

Database Name=flute_examples; Username=flute_16_r, Password=P2TXnnjs. We’ll be keeping this database active for some time into the future so you can run your test project to it if you like.

  1. We’re loading the data to the project from an ESRI shape file and using the database to source value-add data such as country names.

The following code run at form_load time, loads the chart and a datagridview that accompanies the chart on the form.

public Form2()

TeeSHP teeSHP = new TeeSHP();
teeSHP.LoadMap(map1,Path.GetFullPath(Path.GetDirectoryName(Application.ExecutablePath) + “..\\..\\..\\Maps\\world.shp”), dataSet1.Tables[0], “CNTRY_NAME”, “POP_CNTRY”, null, null);

this.dataGridView1.DataSource = dataSet1.Tables[0];

You’ll see we’re using two fields for highlighting in the chart. The map will use the country names (CNTRY_NAME) as label and will use the country population figures (POP_CNTRY) to colourcode each country according to its population ranking.


  1. When you run the project you should see the data loading into the chart as a world map with colourcodings to represent the relative population figures by country. We’ll activate the Marks by code at form load time to display the country labels on each country.

private void Form1_Load(object sender, EventArgs e)
tChart1[0].Marks.Visible = true;


When running the application you should see the above result. Notice that the country names are not visible on all countries; that’s because the label autosizes and if it’s considered that the text is too small to read the label isn’t plotted. Auto-sizing can be disabled or simply zoom the map over the country to see the label displayed.

Example below:


That’s all from the demo project, we hope you may have found it of interest!