Search code examples
c#.netwinformsmicrosoft-chart-controls

Grouped bar chart with WinForms Chart Control


I can create with MS Excel Grouped bar chart like this. enter image description here

I need to create the same Chart via WinForms Chart Control.

I try this code but it seems like I need more sophisticated solution to build correct chart like it does MS Excel.

So help me to correct code in order to build grouped bar chart, please. (And this great Microsoft example does not help https://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=4418 )

DataSource

DataTable dtExc = new DataTable();

// Create columns
dtExc.Columns.Add((new DataColumn("StoodType", typeof(int))).Caption = "Stood");
dtExc.Columns.Add((new DataColumn("TotalMinutes", typeof(double))).Caption = "Time");

foreach (var exDataitem in allDataExc)
{
     DataRow drToAdd = dtExc.NewRow();

     drToAdd[0] = exDataitem.StoodTypeFullName;
     drToAdd[1] = exDataitem.TotalMinutes;

     dtExc.Rows.Add(drToAdd);   
}

Chart

public Chart GenerateExcChart(DataTable dtChartDataSource, int width, int height, string bgColor, SeriesChartType seriesChartType,
            string axisXTitle, string axisYTitle)
        {
            Chart chart = new Chart()
            {
                Width = width,
                Height = height
            };


            chart.Legends.Add(new Legend() { Name = "Legend" });
            chart.Legends[0].Docking = Docking.Bottom;
            ChartArea chartArea = new ChartArea() { Name = "ChartArea" };

            //Remove X-axis grid lines
            chartArea.AxisX.MajorGrid.LineWidth = 0;
            chartArea.AxisX.Title = axisXTitle;

            chartArea.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount;
            chartArea.AxisX.IntervalType = DateTimeIntervalType.Number;

            //Remove Y-axis grid lines
            chartArea.AxisY.MajorGrid.LineWidth = 0;
            chartArea.AxisY.Interval = 1;
            chartArea.AxisY.Title = axisYTitle;

            //Chart Area Back Color
            chartArea.BackColor = Color.FromName(bgColor);
            chart.ChartAreas.Add(chartArea);
            chart.Palette = ChartColorPalette.BrightPastel;
            string series = string.Empty;

            //create series and add data points to the series
            if (dtChartDataSource != null)
            {
                foreach (DataColumn dc in dtChartDataSource.Columns)
                {
                    //a series to the chart
                    if (chart.Series.FindByName(dc.ColumnName) == null)
                    {
                        series = dc.ColumnName;
                        chart.Series.Add(series);
                        chart.Series[series].ChartType = seriesChartType;
                    }

                    var rowIndex = 0;
                    //Add data points to the series
                    foreach (DataRow dr in dtChartDataSource.Rows)
                    {
                        double dataPoint = 0;
                        double.TryParse(dr[dc.ColumnName].ToString(), out dataPoint);

                        var objDataPoint = new DataPoint();
                        objDataPoint.YValues = new double[] { dataPoint };
                        objDataPoint.XValue = rowIndex + 1;
                        objDataPoint.AxisLabel = rowIndex.ToString();

                        if (dataPoint == 0)
                        {
                            objDataPoint.IsEmpty = true;
                        }

                        chart.Series[series].Points.Add(objDataPoint);
                        rowIndex++;
                    }
                }
            }

            return chart;
        }

Solution

  • By using Google and some experiments I corrected code so it does what I need.

    public Chart GenerateExcChart(DataTable dtChartDataSource, int width, int height, string bgColor, SeriesChartType seriesChartType,
                string axisXTitle, string axisYTitle)
            {
                Chart chart = new Chart()
                {
                    Width = width,
                    Height = height
                };
    
                chart.Legends.Add(new Legend() { Name = "Legend" });
                chart.Legends[0].Docking = Docking.Bottom;
                ChartArea chartArea = new ChartArea() { Name = "ChartArea" };
    
                chartArea.AxisX.MajorGrid.LineWidth = 0;//Remove X-axis grid lines
                chartArea.AxisY.MajorGrid.LineWidth = 0;//Remove Y-axis grid lines
    
                chartArea.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount;
                chartArea.AxisY.IntervalAutoMode = IntervalAutoMode.VariableCount;
                chartArea.AxisX.IntervalType = DateTimeIntervalType.Number;
                chartArea.AxisY.IntervalType = DateTimeIntervalType.Number;
    
                chartArea.AxisX.LabelStyle.Angle = -45;
    
                chartArea.AxisX.Title = axisYTitle;
                chartArea.AxisY.Title = axisXTitle;
    
                //Chart Area Back Color
                chartArea.BackColor = Color.FromName(bgColor);
                chart.ChartAreas.Add(chartArea);
                chart.Palette = ChartColorPalette.BrightPastel;
                string series = string.Empty;
    
                //create series and add data points to the series
                if (dtChartDataSource != null)
                {
                    series = "Series1";
                    chart.Series.Add(series);
                    chart.Series[series].ChartType = SeriesChartType.Column;
                    chart.Series[series].XValueType = ChartValueType.Auto;
                    chart.Series[series].YValuesPerPoint = 1;
                    chart.Series[series].YValueType = ChartValueType.Auto;
    
                    var rowIndex = 0;
    
                    //Add data points to the series
                    foreach (DataRow dr in dtChartDataSource.Rows)
                    {
                        double dataPoint;
                        DataPoint objDataPoint = new DataPoint();
    
                        objDataPoint.AxisLabel = dr[dtChartDataSource.Columns[0].ColumnName].ToString();
    
                        double.TryParse(dr[dtChartDataSource.Columns[1].ColumnName].ToString(), out dataPoint);
    
    
                        objDataPoint.XValue = rowIndex;
                        objDataPoint.YValues = new double[] { dataPoint };
    
                        chart.Series[series].Points.Add(objDataPoint);
    
                        rowIndex++;
                    }
                }
    
                chart.Series[0].IsVisibleInLegend = false;
    
                return chart;
            }