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;
begin
  ChartTool1.Text := '0 %';
  Chart1.Hover.Visible := false;

  for i := 0 to Chart1.SeriesCount-1 do
  begin
    Chart1[i].FillSampleValues(2);
    Chart1[i].YValue[0] := 100;
    Chart1[i].YValue[1] := 0;
    Chart1[i].ValueColor[0] := Series1.Pen.Color;
  end;
end;

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

procedure TActivityGaugeForm.FormCreate(Sender: TObject);
begin
  ResetValues;
end;

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

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);
begin
  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
  begin
    Timer1.Enabled := false;
    Timer2.Enabled := true;
  end;
end;

procedure TActivityGaugeForm.Timer2Timer(Sender: TObject);
begin
  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
  begin
    Timer2.Enabled := false;
    Timer3.Enabled := true;
  end;
end;

procedure TActivityGaugeForm.Timer3Timer(Sender: TObject);
begin
  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
  begin
    Timer3.Enabled := false;
    Button1.Enabled := true;
  end;
end;

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.Clear();
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.Refresh();

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";

tChart3[0].CheckDataSource();

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.

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

 

Big files: XML or JSON ? TeeBI !!

TeeBI Dashboards

 

Introduction

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).

Pseudo-code:


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"
end

 

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:

https://github.com/Steema/BI

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:

https://github.com/Steema/BI/wiki/3rd-party-supported-products

 

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

Introduction

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:

https://github.com/Steema/TeeChart-for-.NET-CSharp-WinForms-samples/tree/master/ConnectingToMySql

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.

connect1

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

 

connect2

  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.

 

connect3

  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:

connect4

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

connect5

  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.

connect6

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

 

connect7

 

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

 

tChart1[0].CheckDataSource();

 

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()
{
InitializeComponent();

TeeSHP teeSHP = new TeeSHP();
odbcDataAdapter1.Fill(dataSet1);
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;
}

connect8

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:

Winform_MySQL2

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

What’s New in TeeChart VCL/FMX v2015.16

Build 2015.16.150901

Release September 2015

This technical document describes all changes made to TeeChart component library (FireMonkey and VCL versions) since the release of April 2015.

 

New Supported IDEs

  • Embarcadero RAD Studio 10 Seattle.
    Full support for Delphi and C++ Builder 10 Seattle for all platform projects.

 

‘Detail’ property

Series ‘master-detail’ functionality, with a new ‘Detail’ property and ‘Add’ method overload in the Series class to enable the ‘drill-down’ of Series data.
Example demo available at http://www.teechart.net/files/public/support/SeriesDetailSample.zip

 

TChartLayout component

TChartLayout component, a scrollable panel which will automatically arrange multiple charts into a viewable state.

 

GDI+ canvas Scale property

Creates smoother looking charts. Default value is 1 and can be changed at design and runtime through the Chart editor 3D render dialog.

 

Third legend column support

Support for a third legend column accompanied by a new TextStyle value:
ltsXAndValueAndText.
This shows each point X, Y, and Text label at legend.

 

New Firemonkey dashboard project showcasing TeeChart standard series types

Full sources also available at GitHub:
https://github.com/Steema/TeeChart-for-FireMonkey-applications-samples/tree/master/StandardSeriesDemo

Reaching the browser page with TeeChart

How different versions of TeeChart reach the browser page

 

Recent news that Microsoft are ceasing support for ActiveX with the new navigator, Edge, included with Windows 10, seems to signal the end of mainstream browser support for ActiveX.

ActiveX support was one of the flagship functionality elements for Internet Explorer some years ago but security policies of many organisations, in response to reports of possible intruder exploitation of some aspects of some ActiveX controls, have meant that many applications using ActiveX components have shifted off the browser completely or that browser apps have moved to different formats such as ASP.NET, Java Applets or Javascript/HTML5.

Security clearance for TeeChart ActiveX Control in Internet Explorer

Quite some time ago Steema Software worked extensively with some key customers and CERT (https://www.us-cert.gov/) certification, using their recommendations and analysis tools to make sure that any possible entry points to TeeChart were closed-off. As such, here at Steema we don’t consider TeeChart to offer security weakpoints, but nevertheless, the industry has steadily moved away from ActiveX on the browser and alternative options already needed to be studied as far back as multiple years ago.

This article discusses some of the current options available.

Static Charts on the browser page

All versions of TeeChart are able to work as a serverside component and to generate a static, rendered image of a chart in response to any dynamic input, request or web form post. The response can be quick and effective. Though a static chart offers no interactivity to the person using the application, interactivity is not always necessary or desirable and a static chart has its place as a valid browser page format.

Interactive Charts on the browser page

Interactive Charts on the browser page permit persons using the application to work with the chart, changing its view via a zoom or scroll, or permitting a click/touch on a chart to return more information or insight or to provoke a drill-down in search of more detailed information.

The following sections describe what each version of TeeChart has to offer in terms of interactive charting functionality on the browser.

 

TeeChart for .NET – ASP.NET and WebForm applications

TeeChart for .NET offers a WebChart for placement on a Webform.  The chart is editable via the chart editor at designtime in the Visual Studio IDE and can be run with several interactivity modes:

  • Static Chart; the rendering of a png, jpg or gif format Chart in response to an ASP.NET page query. No interactivity experience for the user other than that offered by external options around the chart such as a combo selection to generate a new chart or view.
  • Interactive Ajax powered Javascript Chart; interaction for mouseclicks locally on page or for drilldown (postback) to server. Charts can be zoomed by mouse or scrolled via a scrollbar. Javascript on the page permits a variety of enhancements to affect how the chart reacts to interaction. User experience for interaction at this level is of a moderate to good level.
  • Interactive HTML5 Canvas powered Chart. The designtime editing options remain the same as for previous options but the chart is rendered on a fully interactive HTML5 Javascript powered Canvas that allows pageside javascript to control some aspects of the charting experience and for others to be fed back to the serverside module. Not all TeeChart for .NET’s Series types can be rendered to the HTML5. User experience in terms of interactivity is of a very high level as the HTML5 chart is a live component on the page with full access at runtime to the TeeChart for Javascript charting library.

 

TeeChart for Javascript, HTML5 applications

TeeChart for Javascript is a pure-for-the-web-browser designed Component. This version of TeeChart, also referred to as TeeChart for HTML5, requires to be designed by an HTML page designer with facility to edit on-page Javascript (notepad will do) and offers a very high level of interactivity to the browser page viewer as the chart is fully live in the page with dynamic access to the full TeeChart for HTML5 component library. HTML5 charts can reach virtually any platform as nearly all current browsers natively support Javascript and the HTML5 canvas.

 

TeeChart in HTML5. Live zoom/scroll/click
TeeChart for Javascript/HTML5.

TeeChart for Java, Servlet and Applet applications

TeeChart for Java powered web browser applications may be viewed on the browser page as a Java applet. A Java applet is, in effect, a standalone application on the browser page and offers functionality and a way of working, similar in many respects to the TeeChart ActiveX control. Applet support in the browser is in decline and appears to be going the same way as ActiveX Control support as many organisations add restrictions to the technology types they are willing to support on browser platforms. More recent versions of browsers have imposed further security restrictions demanding code-signing of controls that are allowed to be run on the browser page. If you decide to start a new project using Java Applets as the means to take TeeChart to the browser page, we recommend you check first, the current situation for browser support and certification requirements.

A Java servlet runs at the server and is able to return static Charts as images to client browser applications in response to dynamic requests.

 

TeeChart for VCL

TeeChart for VCL can reach the browser with a fully interactive Chart via Delphi’s ActiveForm technology. As ActiveForm is an ActiveX control, support for it will be dropped from the Edge browser included with Windows 10 so we recommend you confirm the browser platform to be used before starting new development projects for that environment with it.

TeeChart for VCL also supports export to HTML5, thus offering fully live charts on the browser page. Export is supported for a limited set of Series types only.

 

TeeChart for PHP

TeeChart for PHP is designed to respond to dynamic requests at a web server to provide charts in static or dynamic formats. The current supported dynamic format is HTML5 and TeeChart for PHP works in unison with TeeChart for HTML5 to create a javascripted clientside, fully interactive chart.

 

TeeChart for ActiveX, ASP applications

TeeChart for ActiveX has been discussed at the opening of this article. It is a very powerful way to deliver a web application to a browser, being similar in nature to a desktop application on the browser page. ActiveX has only ever been supported on Internet Explorer (apart from some addins available in the past for other browsers) which limits its public a little. The phasing out of support for ActiveX for the default browser, Edge, in Windows 10 means that it is probably best avoided when considering developing new browser applications going forward. TeeChart for ActiveX remains an extremely useful tool for virtually all other COM compatible containers and can be used to create static charts for the browser page with javascript enhancements for hotspots.

Alternatively the TeeChart for ActiveX version may still be used to generate live, interactive charts in HTML5 for virtually all browsers. Note that HTML5 export is supported for a limited set of Series types only.

Check out the new StandardSeriesDemo example

Check out the new StandardSeriesDemo example which has been created for most of the Steema TeeChart products.

You can download and check the source code for each TeeChart version at the Steema GitHub page :

https://github.com/Steema/TeeChart-for-.NET-CSharp-WinForms-samples/tree/master/StandardSeriesDemo (for TeeChart for NET WinForms -CSharp).

https://github.com/Steema/TeeChart-for-FireMonkey-applications-samples/tree/master/StandardSeriesDemo (for TeeChart for FireMonkey FMX).

https://github.com/Steema/TeeChart-ActiveX-samples/tree/master/StandardSeriesDemo (for TeeChart ActiveX).

https://github.com/Steema/teechart-xamarin-foms-samples/tree/master/StandardSeriesDemo (for TeeChart for Xamarin.Forms).

https://github.com/Steema/TeeChart-Java-for-Swing-applications-samples/tree/master/StandardSeriesDemo (for TeeChart for Java).

StandardSeriesDemo1 StandardSeriesDemo2 StandardSeriesDemo3 StandardSeriesDemo4

 

Clustering visualization

TeeChart Pro includes classes and components to perform “clustering” on your data, and optionally visualize the results using a chart “Tool” component.

Clustering is the process of grouping data automatically, according to how well related are the individual items.

As an unsupervised algorithm, its widely used in data-mining / machine-learning / B.I. (Business Intelligence) applications.

 

teechart_clustering

For more information on clustering visit the following Wikipedia link: http://en.wikipedia.org/wiki/Cluster_analysis

An executable example:

http://www.steema.us/files/public/teechart/vcl/demos/clustering/TeeChart_Clustering.zip

The clustering algorithm can be processed on custom data, not necessarily on TeeChart “Series” data.

 

Classes and Units

The TeeClustering.pas unit, for both VCL and Firemonkey, contains abstract “engine” classes that perform the clustering algorithms.

Three different clustering methods are provided:

• TKMeansClustering

• THierarchicalClustering

• TQTClustering (Quality Threshold)

These classes derive from a common abstract class: TBaseClustering.

Each clustering method has its own properties that determine how will the clusters be calculated. After calculating, you can access the Clusters property, which is a TList of TCluster objects.

A TCluster contains child clusters (Items[ ]), so you can check which input data items belong to which cluster, or in the case of the Hierarchical type, access the tree structure (clusters and sub-clusters).

The input data (your data) is not contained by the above classes.

Data is passed to the clustering engine through a “provider” class. There is currently one kind of data provider (TSeriesProvider) to cluster XY or XYZ Series points.

This class is implemented in the TeeClusteringTool.pas unit, together with a charting Tool class (TClusteringTool) to make things easier and more automatic.

 

Basic Example

Example runtime code (it can be done at design-time too, without coding) :

uses TeeClusteringTool;

var tool : TClusteringTool;

tool:=TClusteringTool.Create(Self);

tool.ParentChart:=Chart1;

tool.Series:=Series1; // your series

tool.Method:=cmKMeans;

tool.KMeans.NumClusters:=5;

tool.Execute;

 

After execution, you can loop on the resulting output clusters, for example:

var t : Integer;

for t:=0 to tool.Clusters.Count-1 do
Memo1.Lines.Add( ‘Cluster: ‘+IntToStr(t)+’ contains:  ‘+
IntToStr(tool.Clusters[t].Count)+’ points’ );

 

 

TClusteringTool

This tool automatically performs clustering using the choosen method and parameters, and optionally paints each source series point with a different color indicating which cluster they belong to, and/or draws polygons around each group of cluster’s items, among other things.

Properties:

ClusteringTool1.Method := cmHierarchical;

ClusteringTool1.ColorEach := True; // paint Series with one color per cluster

ClusteringTool1.ShowBounds := True; // draws convex polygons bounding each cluster points

ClusteringTool1.Centers.Visible := True; // shows cluster centers

ClusteringTool1.Centroids.Visible := True; // shows cluster centroids

Other properties include Brush, Pen and Transparency, used when drawing cluster polygon boundaries.

Methods:

Several helper methods are provided:

// Obtain cluster’s center and centroid XY points in Series scales:

var P : TPointFloat;

P:=ClusteringTool1.GetClusterCenter( ClusteringTool1.Clusters[3] );

P:=ClusteringTool1.GetClusterCentroid( ClusteringTool1.Clusters[2] );

// Obtain an array of XY points (in screen pixel coordinates), that belong to cluster:

var PP : TPointArray;

ClusteringTool1.GetClusterPoints( ClusteringTool1.Clusters[4], PP);

PP:=nil;

// Get cluster statistics:

var S : TClusterStats;

S:=ClusteringTool1.GetStats( ClusteringTool1.Clusters[0] );

 

Calculation parameters

Each clustering algorithm needs different parameters:

K-Means:

ClusteringTool1.KMeans.NumClusters := 10; // Number of minimum clusters (“K”)

ClusteringTool1.KMeans.MaxIterations := 1000; // Maximum number of iterations before stopping

Hierarchical:

ClusteringTool1.Hierarchical.NumClusters := 8; // Number of tree root clusters

QT:

ClusteringTool1.QTClustering.MinCount := 30; // Minimum number of points to form a cluster

ClusteringTool1.QTClustering.MaxDiameter := 100; // Maximum “diameter” a cluster can grow

 

Common parameters:

Distance

Cluster calculation is based on the “distance” between a data item and the other data items. There are several ways to calculate the “distance” between items.

The algorithms are agnostic, they call the Provider (ie: Series provider) to obtain the distances.

For example, on a XY scatter plot, the distance between points can be for example the hypotenuse (Pythagoras’ theorem), that is, the simple Euclidean distance between a point XY and another XY.

Distance calculations implemented:

dmEuclidean
dmSquaredEuclidean
dmManhattan
dmMinkowski
dmSorensen
dmChebyshev

 

Example:

ClusteringTool1.Distance := dmMinkowski;

ClusteringTool1.MinkowskiLambda := 4;

 

Linkage

There are several ways to calculate the “distance” between clusters when one or the two clusters have more than one item.

This is called “linkage”.

The most simple way is using each cluster “center” (this means no linkage occurs).

Other linkage styles implemented:

lmSingle

Also called “minimum”.

The distance between cluster A and B is the minimum distance between all items in cluster A and all items in cluster B.

lmComplete

Also called “maximum”.

The distance between cluster A and B is the maximum distance between all items in cluster A and all items in cluster B.

lmAverage

The distance between cluster A and B is the average distance between all items in cluster A and all items in cluster B.

lmWard

The result is the increase on “error sum of squares” when adding cluster B items to cluster A.

 

Calculation speed

Clustering is a slow process by nature. Each clustering method has different performance bottlenecks, proportional to the number of input data items.

The TeeClustering.pas unit has been greatly fine-tuned to optimize the speed of each algorithm, although much work is needed to find more advanced techniques that require less CPU cycles.

The QT Threshold algorithm benefits of parallelism, when multiple CPUs can be used together.

Speed examples (revisited):

(Time in milliseconds, Windows 8.1 x64 on Intel i7 4770 @ 3.4Ghz)

IDE XE8 Delphi, Win32, 5000 data points

Algorithm      Single CPU   Multiple CPU

K-Means              47                     31
Hierarchical    4328                4156
QT                     2859                  703

Notes:

x64 bit executables are a little bit faster than 32bit.

Speed is also very dependant on the “distance” calculation method that is used to compare data.  The default Euclidean calculation has a quite big CPU cost as it calculates the Hypotenuse between two data XY value pairs.

 

 

DashBoards and Data Visualization using Xamarin.Forms and TeeChart

DashBoards and Data Visualization using Xamarin.Forms and TeeChart

This article is going to show how easy it is to create dashboard designs to show information, especially data, by using the layouts included in Xamarin.Forms and how to use the TeeChart charting library, which fully supports Xamarin.Forms.

In this example several Charts will be added to the layout, choosing a specific design which will be adjusted for each device depending on the platform chosen.

The first step is to create a new Xamarin.Forms application (Portable)
New Project -> Visual C# -> Mobile Apps -> Blank App (Xamarin.Forms.Portable)

image1

 

Now, we’re going to add the TeeChart for Xamarin.Forms libraries as a reference to our projects to be able to use it.

Find the dlls for each specific platform on your hard disk (at the TeeChart for Xamarin.Forms installation folder). The TeeChart.PCL library also has to be referenced in all the projects.

 

Adding the TeeChart for Xamarin.Forms library as reference to the project.

 

TeeChart.PCL for the TeeChartDashBoards Portable project

TeeChart.PCL.Android.dll for the TeeChartDashBoards.Droid project

TeeChart.PCL.iOS.Unified.dll for the TeeChartDashBoards.iOS project

TeeChart.WP8.dll for the TeeChartDashBoards.WinPhone project

 

In order to make use of the TeeChart charting library we need to create a View which will contain the Chart component on it to be able to add it on our project, this “ChartView.cs” class has to be defined into the main project  (all the platforms will make use of it).

 

To create, just add a new class to the TeeCahrtDashBoards Portable project and add the following code to it :

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace TeeChartDashBoards
{
public class ChartView: View
{
public ChartView()
{
}

public EventHandler OnInvalidateDisplay;

public static readonly BindableProperty ModelProperty =
BindableProperty.Create(“ModelProperty”, typeof(Steema.TeeChart.Chart), typeof(ChartView), null);

public Steema.TeeChart.Chart Model
{
get { return (Steema.TeeChart.Chart)GetValue(ModelProperty); }
set { SetValue(ModelProperty, value); }
}

public void InvalidateDisplay()
{
if (OnInvalidateDisplay != null)
OnInvalidateDisplay(this, null);
}
}
}

 

 

Now, in order to make use of the ChartView, a renderer class is needed for each specific platform, so we’ll create a new class named “ChartViewRenderer.cs” for each platform and add the following code :

image2

This is the code for the Android project :

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Steema.TeeChart;
using TeeChartDashBoards;

[assembly: ExportRenderer(typeof(ChartView), typeof(ChartViewRenderer))]
namespace TeeChartDashBoards.Droid
{
public class ChartViewRenderer: ViewRenderer
{
protected TChart NativeControl
{
get
{
return ((TChart)Control);
}
}

protected ChartView NativeElement
{
get
{
return ((ChartView)Element);
}
}

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);

if (Control == null)
{
var chartView = new Steema.TeeChart.TChart(Context);

chartView.Chart = NativeElement.Model;

SetNativeControl(chartView);
}

if (e.OldElement != null)
{
//unhook old events
}

if (e.NewElement != null)
{
//hook old events
}
}
}
}

 

Do the same for the iOS project, adding the following code :

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using TeeChartDashBoards;

[assembly: ExportRenderer(typeof(ChartView), typeof(TeeChartDashBoards.iOS.ChartViewRenderer))]
namespace TeeChartDashBoards.iOS
{
public class ChartViewRenderer : ViewRenderer<ChartView, Steema.TeeChart.TChart>
{
protected override void OnElementChanged(ElementChangedEventArgs<ChartView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || this.Element == null)
return;

var chartView = new Steema.TeeChart.TChart();

chartView.Chart = Element.Model;

SetNativeControl(chartView);
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
}
}

 

and the for the WinPhone project :

 

using TeeChartDashBoards;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Platform.WinPhone;

[assembly: ExportRenderer(typeof(ChartView), typeof(TeeChartDashBoards.WP8.ChartViewRenderer))]
namespace TeeChartDashBoards.WinPhone
{
public class ChartViewRenderer : ViewRenderer<ChartView, Steema.TeeChart.TChart>
{
protected override void OnElementChanged(ElementChangedEventArgs<ChartView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || this.Element == null)
return;

var chartView = new Steema.TeeChart.TChart();

chartView.Chart = Element.Model;
chartView.Aspect.ClipPoints = false;
chartView.Aspect.ExtendAxes = true;

SetNativeControl(chartView);
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
}
}

 

At this point, if we do “build solution” all should compile fine.

That being the case, it’s time to create a new Content Page in the main project, the initial page which will appear once the app is launched in one of the available platforms. Set “Home.cs” as the name for the page.

The solution should look like :

image3

Inside this page, the first thing we’ll do is to remove all the code that has been generated by default and will add a code that creates a Navigation page which will allow us to navigate through all the Charts inside the dashboard :

 

public Home()
{
NavigationPage.SetHasNavigationBar(this, false);
}

 

Now, we’ll define the layout, choosing the Grid layout that fits our needs. The grid layout allows one to specify the number of rows and columns to show and define the rowspan or colspan if needed (this will allow us to make the dashboard nicer) :

 

Grid grid = new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
Padding = 5,
RowDefinitions =
{
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }
},
ColumnDefinitions =
{
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
}
};

Content = grid;

 

Now it’s time to create the Charts that will be added on our dashboard. We’ll add seven Charts. First of all, we’ll create a “DashBoards” folder in the main project to add the content pages there, one for each chart. This folder has to be created one time in the main project (Portable).

Each page will define a specific chart with the Series used on it and its customised appearance. We’ll start with the content page named Page1.cs. We’ll use the following code:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using Steema.TeeChart;

using Xamarin.Forms;

namespace TeeChartDashBoards.DashBoards
{
public class Page1 : ContentPage
{
Chart dashBoard0;
public ChartView DashView0;
public Page1()
{
// NavigationPage.SetHasNavigationBar(this, false);

dashBoard0 = new Chart();
dashBoard0.Aspect.View3D = false;
Steema.TeeChart.Styles.Bar bar1 = new Steema.TeeChart.Styles.Bar();
Steema.TeeChart.Styles.Line line1 = new Steema.TeeChart.Styles.Line();
dashBoard0.Series.Add(bar1);
dashBoard0.Series.Add(line1);
//barline chart
bar1.Clear();
bar1.Add(20);
bar1.Add(50);
bar1.Add(10);
bar1.Add(70);
bar1.Add(46);
bar1.Pen.Visible = false;
bar1.BarStyle = Steema.TeeChart.Styles.BarStyles.RectGradient;
bar1.Marks.Visible = false;
bar1.Gradient.StartColor = Color.White;
bar1.Gradient.EndColor = Color.FromRgb(102, 205, 170);
bar1.Marks.Visible = true;
bar1.Marks.Shadow.Visible = false;
bar1.Marks.Color = Color.White;
bar1.Marks.Font.Size = 15;
bar1.Marks.Font.Color = Color.FromRgb(102, 205, 170);
bar1.Marks.Pen.Visible = false;
bar1.Marks.ArrowLength = 5;
bar1.Color = Color.White;

line1.Clear();
line1.Add(0, 45);
line1.Add(0.444444444444444, 55);
line1.Add(0.888888888888889, 75);
line1.Add(1.33333333333333, 65);
line1.Add(1.77777777777778, 45);
line1.Add(2.22222222222222, 80);
line1.Add(2.66666666666667, 85);
line1.Add(3.11111111111111, 98);
line1.Add(3.55555555555556, 75);
line1.Add(4, 68);
line1.Color = Color.FromRgb(255, 255, 240);

line1.LinePen.Width = 3;
line1.Smoothed = true;

dashBoard0.Panel.Color = Color.FromRgb(102, 205, 170);
dashBoard0.Panel.Gradient.Visible = false;
dashBoard0.Walls.Back.Visible = false;
dashBoard0.Title.Text = “Bars and Lines”;
dashBoard0.Title.Alignment = TextAlignment.Start;
dashBoard0.Title.Font.Size = 22;
dashBoard0.Title.Font.Color = Color.White;
//dashBoard0.Title.Font.Name = “”;
dashBoard0.Axes.Left.AxisPen.Visible = false;
dashBoard0.Axes.Bottom.AxisPen.Color = Color.White;
dashBoard0.Legend.Visible = false;
dashBoard0.Axes.Left.Grid.Color = Color.White;
dashBoard0.Axes.Left.Grid.Style = Steema.TeeChart.Drawing.DashStyle.Dot;
dashBoard0.Axes.Left.Labels.Font.Color = Color.White;
dashBoard0.Axes.Bottom.Labels.Font.Color = Color.White;
dashBoard0.Axes.Left.Increment = 25;

DashView0 = new ChartView
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
DashView0.Model = dashBoard0;

Content = new StackLayout
{
Children = {
DashView0
}
};
}
}
}

 

The code above defines a Chart component for the page, adds some series styles to it and then set some custom aspects. I’m not going to add all the seven code pages here, as the same code structure has to be used, just that we can use other Series types and change the aspect settings as preferred. You will find the ones I have chosen by downloading the complete example at the bottom of the page. In order to follow this article do the same for other pages (Page2.cs, Page3.cs,…) as you have done for the first page.

 

 

Now that we have all the Chart styles (pages) we want to appear in our dashboard we’ll go back to the home page to add the necessary code to call each one of the pages and add it to the dashboard.

From here we call each one of the pages generated to be added to each of the cells of the grid; in this way we avoid having to recreate the charts.

First we create the seven DashBoard Charts, just before assigning the content to the grid:

 

// Create the Chart pages whose contain a specific Chart on each one
DashBoards.Page1 dashchart0 = new DashBoards.Page1();
DashBoards.Page2 dashchart1 = new DashBoards.Page2();
DashBoards.Page3 dashchart2 = new DashBoards.Page3();
DashBoards.Page4 dashchart3 = new DashBoards.Page4();
DashBoards.Page5 dashchart4 = new DashBoards.Page5();
DashBoards.Page6 dashchart5 = new DashBoards.Page6();
DashBoards.Page7 dashchart6 = new DashBoards.Page7();

 

To be able to navigate between each Content Page (available Chart pages) I’ve decided to create a button and add it to each cell. Some other ways might also work in order to execute part of code once cell is tapped, but this one allows one to do it easily, and also this way, lets us take advantage of the button class functionalities.

We need to create a button for each dashChart. Here’s the code for one of them :

 

Button button0 = new Button()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Command = new Command(() => Navigation.PushAsync(new DashBoards.Page1()))
};

 

And now we’ll add all the Charts and buttons created to the Grid layout. I’ve chosen some specific rowspan and colspan for some cells, just to look better, but anyone can customise it their way:

 

// Grid
grid.Children.Add(dashchart0.DashView0, 0,2,0,1);
grid.Children.Add(button0,0,2,0,1);
grid.Children.Add(dashchart1.DashView1, 2,4,0,1);
grid.Children.Add(button1,2,4,0,1);
grid.Children.Add(dashchart2.DashView2, 0, 1);
grid.Children.Add(button2,0, 1);
grid.Children.Add(dashchart3.DashView3, 1, 3, 1, 2);
grid.Children.Add(button3, 1,3,1,2);
grid.Children.Add(dashchart4.DashView4, 3,4,1,3);
grid.Children.Add(button4, 3, 4, 1, 3);
grid.Children.Add(dashchart5.DashView5, 0, 2, 2, 3);
grid.Children.Add(button5, 0, 2, 2, 3);
grid.Children.Add(dashchart6.DashView6, 2, 2);
grid.Children.Add(button6, 2, 2);

 

The last steps are to modify the App.cs class. This one needs to call the Home.cs content page :

 

public App()

{
// The root page of your application
MainPage = new NavigationPage(new Home());
}

 

We’ve also to modify the MainPage.xaml.cs page in order for it to work fine on WinPhone :

 

public MainPage()
{
InitializeComponent();

Forms.Init();
Content = new TeeChartDashBoards.Home().ConvertPageToUIElement(this);
}

 

Now we’re going to try to do a build for all the projects, run the app on each platform (IOS, Android y WinPhone) and see the results.

 

The source code of this example can be downloaded from the Steema GitHub page.

 

The result should look like:

grid