Skip to main content Skip to footer

Introducing FlexChart in C1FlexPivot

Introducing FlexChart in C1FlexPivot

Charts integrated within ComponentOne FlexPivot for WinForms are now rendered using FlexChart. FlexChart has a modern look and is more powerful than the legacy C1Chart control used in older versions.

In this post, we'll walk through the new chart features of FlexPivot and show a real-world sample analyzing data.

FlexPivot vs. C1FlexPivot

To support backward compatibility, we kept the old charts within the C1FlexPivot component. In this last release we introduced a new FlexPivot control that uses the new FlexChart.

FlexPivot consists of three major components: PivotPanel, PivotChart, and PivotGrid. C1FlexPivot and FlexPivot differ by the component they use in PivotChart charting functionalities. C1FlexPivot used C1FlexPivotChart which was based on C1Chart control.

How FlexChart Benefits FlexPivot

FlexChart has been a ComponentOne .NET flagship charting component (since 2016). Here are several advantages of FlexChart:

  • Support for DirectX rendering for better performance
  • Lightweight, faster, and better performance than C1Chart for both small and large data
  • Support for 80+ chart types
  • Easy-to-use API enabling easier extension and customization of the control

Let’s see how FlexPivot uses FlexChart. Using FlexChart as its underlying charting component, FlexPivot offers the following features:

  • FlexPivotChart.UseAxisScrollbar: With this property, FlexPivot automatically shows the Axis scrollbar when the number of labels/data points to render are large. This feature utilizes a modern approach of scrolling through the chart, analyzing the selected range of data in detail.
  • FlexPivotPage.Palette: FlexPivot has a set of color schemes for rendering a data series. The color schemes are modern and easy to set.
  • Flexibility to work directly with FlexChart: The FlexPivotChart presents the Chart property. This allows for additional chart customizations.

Use Case - Analyzing Global COVID-19 Data

Let’s consider a scenario where a research and data publication agency needs to show global COVID-19 statistics. In this example, the agency needs a tool that allows dynamic data analysis and data visualization.

Additionally, as the COVID-19 data is presented for each date of a specific time frame, the data points will be large. The control should allow run-time interaction enabling the user to analyze the data at a granular level, by selecting the area they want to enlarge.

FlexPivot and FlexChart can be used for this example. The below image represents global COVID-19 statistics:

Introducing FlexChart in C1FlexPivot

Here, each data point in the chart represents one of the following COVID-19 data points:

  • New COVID-19 positive cases reported against the specific date
  • New deaths due to COVID-19 infection reported against the specific date
  • Total COVID-19 positive cases reported till the specific date
  • Total deaths due to COVID-19 reported till the specific date

We’re dividing the implementation into the following parts:

  1. Binding FlexPivot to a data source
  2. Referencing chart in FlexPivot
  3. Customizing FlexChart

Binding FlexPivot

Binding FlexPivot is simple. Just set the property to DataSource. To show how easy it is to use FlexPivot to visualize real-time data, we'll display data for ‘COVID-19 information’ from OurWorldInData. The data taken for consideration contains information for the time span: December 31st, 2019 - May 31st, 2020.

To reflect this data in FlexPivot, we need to have a blueprint of the data to which we can bind our pivot. We will create the following class for this:

public class CovidData 

{ 
        public DateTime Date { get; set; } 
        public double TotalCases { get; set; } 
        public double TotalDeaths { get; set; } 
        public double NewCases { get; set; } 
        public double NewDeaths { get; set; } 
} 

Once we have created the blueprint of our data, we can now bind FlexPivot and add fields to RowValues and ValueFields:


var data = DataLoader.Import(countryName); 
flexPivotPage.DataSource = data; 
    flexPivotPage.FlexPivotEngine.RowFields.Add("Date"); 
    flexPivotPage.FlexPivotEngine.ValueFields.Add("TotalCases"); 
    flexPivotPage.FlexPivotEngine.ValueFields.Add("NewCases"); 
    flexPivotPage.FlexPivotEngine.ValueFields.Add("TotalDeaths"); 
    flexPivotPage.FlexPivotEngine.ValueFields.Add("NewDeaths");

The following image shows data loaded in the FlexPivot after completion of this step:

Introducing FlexChart in C1FlexPivot

Here, the chart renders the COVID-19 statistics: total cases, total deaths, new cases, and new deaths for each date.

Notice that the data set is large and the changes in data points appear very small. Therefore, in the next sections, we’ll cover how to customize the chart to create effective visualizations.

Referencing Charts in FlexPivot

To make the data more meaningful to the user, we need to access the underlying FlexChart charting component in FlexPivot, then customize it.

In FlexPivot, FlexChart can be accessed through the FlexPivotChart.Chart property as follows:


var flexChart = flexPivotPage.FlexPivotChart.Chart as FlexChart; 

Customizing FlexChart

Once we have access to FlexChart we can take advantage of its rich features and customize the chart output in FlexPivot.

The following section illustrates how to implement FlexChart features:

Composite Charts

To improve data presentation, we will render COVID-19 parameters with different chart types.

With C1FlexPivot, we could display only two chart types as C1Chart had only two ChartGroups available. Whereas, with the FlexPivot, we can specify the chart type for an unlimited number of series.

To access the series and change their ChartType, we use the CollectionChanged event of the Series collection, as follows:


// gets FlexChart's Series collection 
var seriesColl = flexChart.Series as ObservableCollection<Series>; 
seriesColl.CollectionChanged += SeriesColl_CollectionChanged; 
private void SeriesColl_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 

{ 
         // handles only if a Series is added to FlexChart 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) 

        { 
                var series = e.NewItems[e.NewItems.Count - 1] as Series; 
                if (series == null) 
                    return; 
                switch (series.Name) 
                { 
                    case "TotalCases": 
                        series.ChartType = C1.Chart.ChartType.Line; 
                       break; 
                    case "NewCases": 
                        series.ChartType = C1.Chart.ChartType.Step; 
                        break; 
                    case "TotalDeaths": 
                        series.ChartType = C1.Chart.ChartType.Column; 
                        break; 
                    case "NewDeaths": 
                        series.ChartType = C1.Chart.ChartType.Column; 
                       break; 
                } 
         } 
} 

Introducing FlexChart in C1FlexPivot

Multiple Secondary Axes

The value of COVID-19 parameters varies. For instance, the new COVID-19 cases on May 18th are 81,217, whereas total cases are 4,679,764. If we try to visualize multiple series in one plot-area, the series ‘NewCases’ with smaller value will become insignificant w.r.t ‘TotalCases.’ Therefore, we need to add an axis for each series.

With C1Chart, we could plot a maximum of three axes; however, FlexChart allows us to plot one or more data series on a secondary axis. To add axis for each series, we again use the CollectionChanged event and set the AxisY property in a way that the above code becomes as follows:


private void SeriesColl_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 

{ 
        // handles only if a Series is added to FlexChart 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) 
        { 
                var series = e.NewItems[e.NewItems.Count - 1] as Series; 
                if (series == null) 
                    return;  
                switch (series.Name) 
                { 
                    case "TotalCases": 
                        series.ChartType = C1.Chart.ChartType.Line; 
                        series.AxisY = new Axis() 
                        { 
                            AxisLine = true, 
                            Position = C1.Chart.Position.Left, 
                            Title = "Total patients diagnosed +ve with COVID-19", 
                            Format = "0,0" 
                        }; 
                        break; 
                    case "NewCases": 
                        series.ChartType = C1.Chart.ChartType.Step; 
                        series.AxisY = new Axis() 

                        { 
                            Position = C1.Chart.Position.Left, 
                            AxisLine = true, 
                            Title = "Daily new patients diagnosed +ve with COVID-19"                             
                        }; 
                        break; 
                    case "TotalDeaths": 
                        series.ChartType = C1.Chart.ChartType.Column; 
                        series.AxisY = new Axis() 
                        { 
                            AxisLine = true, 
                            Position = C1.Chart.Position.Right, 
                            Title = "Total deaths due to COVID-19", 
                            Format = "0,0" 
                        }; 
                        break; 
                    case "NewDeaths": 
                        series.ChartType = C1.Chart.ChartType.Column; 
                        series.AxisY = new Axis() 
                        { 
                            Position = C1.Chart.Position.Right, 
                            AxisLine = true, 
                            Title = "New deaths due to COVID-19" 
                        }; 

                        break; 
                } 
        } 
} 

Introducing FlexChart in C1FlexPivot

Axis Scrollbar

The data set used in this article contains COVID-19 information for each date from December 31st, 2019 - May 31st, 2020. As the data becomes larger, the elements rendered against each data point become smaller, which becomes difficult to understand.

FlexChart resolves this problem by exposing a scrollbar that allows decreasing the range of data points in view. FlexPivot extends this feature by exposing a property FlexPivotChart.UseAxisScrollbar that automatically shows the Axis scrollbar when the number of labels/data points to render is large. Just use the scrollbar to increase/decrease the data in the view.


flexPivotPage.FlexPivotChart.UseAxisScrollbar = true; 

Zoom

The data under observation can range from having a few tens of data points to a few thousand. With so many points, it would be ideal to have zooming capabilities.

To enable zoom in FlexChart, we need to handle MouseDown, MouseUp, and MouseMove events.


Point _start, _last; 
        bool _IsMouseDown; 
        private void FlexChart_MouseUp(object sender, MouseEventArgs e) 
        { 
            var flexChart = sender as FlexChart; 
            // resets zooming in FlexChart 
            if(e.Button== MouseButtons.Right) 

            { 
                flexChart.AxisX.Min = flexChart.AxisX.Max = double.NaN; 
                flexChart.AxisY.Min = flexChart.AxisY.Max = double.NaN; 
            } 

            // stops Zooming 
            _IsMouseDown = false; 
            if (!_last.IsEmpty) 

            { 
                var start = flexChart.PointToData(_start); 
                var last = flexChart.PointToData(_last); 
                // updates axes with new limits 
                flexChart.AxisX.Min = Math.Min(start.X, last.X); 
                flexChart.AxisX.Max = Math.Max(start.X, last.X); 
                flexChart.AxisY.Min = Math.Min(start.Y, last.Y); 
                flexChart.AxisY.Max = Math.Max(start.Y, last.Y); 
            } 

            // clean up 
            _start = _last = Point.Empty; 

        } 

private void FlexChart_MouseDown(object sender, MouseEventArgs e) 

{ 
            var flexChart = sender as FlexChart;  
            // starts Zooming 
            _IsMouseDown = true; 
            _start = e.Location; 
            _last = Point.Empty; 
} 
private void Chart_MouseMove(object sender, MouseEventArgs e) 
{ 
            var flexChart = sender as FlexChart; 
             // when zooming, update selection range 
            if (_IsMouseDown) 
            { 
                var ptCurrent = e.Location; 
                var left = (int)flexChart.PlotRect.Left; 
                var right = (int)flexChart.PlotRect.Right; 
                var top = (int)flexChart.PlotRect.Top; 
                var bot = (int)flexChart.PlotRect.Bottom; 
                ptCurrent.X = ptCurrent.X < left ? left : ptCurrent.X > right ? right : ptCurrent.X; 
                ptCurrent.Y = ptCurrent.Y < top ? top : ptCurrent.Y > bot ? bot : ptCurrent.Y; 
                _last = ptCurrent; 
                flexChart.Refresh(); 
            } 
} 

Introducing FlexChart in C1FlexPivot

Legend Toggle

With FlexChart, we can also focus on specific COVID-19 parameters by enabling only a specific series and disabling the rest. This can be done by setting the LegendToggle property to true.


flexChart.LegendToggle = true; 

Introducing FlexChart in C1FlexPivot

Here, the series ‘TotalDeaths’ and ‘TotalCases’ have been disabled so that their data is no more visible in the chart.

Selection Mode

FlexChart has built-in support for selection. By enabling the Selection Mode, users can differentiate the selected COVID-19 parameter from other parameters and display information related to the selected parameter.

For example, if we want to display information of all COVID-19 parameters as a tooltip when the user selects a data point, we can access information for the selected data point.

For this, we will handle the MouseDown and MouseMove events of FlexChart as follows:


flexChart.SelectionMode = ChartSelectionMode.Point; 
private void FlexChart_MouseDown(object sender, MouseEventArgs e) 

{ 
            var flexChart = sender as FlexChart;   
            var hitTestInfo = flexChart.HitTest(e.Location); 
            if (hitTestInfo == null || hitTestInfo.Item == null) 
                return; 
            if (hitTestInfo.ChartElement == ChartElement.PlotArea) 
            { 
                _selectedLocation = e.Location; 
            } 
} 

private void Chart_MouseMove(object sender, MouseEventArgs e) 

{ 
            var flexChart = sender as FlexChart; 
           // get details for selected element 
           CovidData selectedData = (((flexChart.Parent as FlexPivotChart).DataSource as C1FlexPivotPanel).DataSource as List<CovidData>).OrderBy(c => c.TotalCases).ToList()[flexChart.SelectedIndex] as CovidData; 

            if (selectedData != null) 
            { 
                        var tooltipTemplate = @"**Date: {0}" + Environment.NewLine + "**Total Cases: {1}" + Environment.NewLine + "**Total Deaths: {2}" + Environment.NewLine + "**New Cases: {3}" + Environment.NewLine + "**New Deaths: {4}"; 

                        var tooltipContent = String.Format(tooltipTemplate, selectedData.Date.ToLongDateString(), selectedData.TotalCases, selectedData.TotalDeaths, selectedData.NewCases, selectedData.NewDeaths); 

                        flexChart.ToolTip.Content = tooltipContent; 
           } 
} 

Introducing FlexChart in C1FlexPivot

Here, once a data point is selected, information for all COVID-19 parameters is shown as its ToolTip.

Chart Palette

FlexPivot introduces multiple easy-to-use chart palettes. Selected this by setting the Palette property.


flexPivotPage.Palette = Palette.Darkly; 

Introducing FlexChart in C1FlexPivot

The above image shows FlexPivot chart ‘FlexChart’ with the Palette ‘Darkly.’ With the above chart, it's easier to plot and understand the COVID-19 information with multiple secondary axes, different chart types, customized tooltip information, and the ability to scroll and zoom to any specific date range.

We have plans to extend FlexChart support in FlexPivot by adding more chart types and functionalities.

FlexChart Benefits

The inclusion of FlexChart will add many benefits to the FlexPivot control. Users have the ability to use multiple secondary axes, zooming in/out, scrollbar functionality with large data sets, composite charts, the ability to view the data by legend toggling selectively, and enhanced tooltips.

Our development team plans to add support for additional FlexChart features in upcoming releases!

Download FlexPivotPage Demo

Ruchir Agarwal

comments powered by Disqus