1

Intro:

This pseudocode is based on Multiple chart areas in one column, however, when I enable many chart areas and all of them are aligned one above the other, the graphic height is getting lower while the axis X labels are getting away from the chart.

Let's see this in a deep way:

enter image description here

I have a panel which contains inside itself the chart. Every chart area makes reference to a selected resource, so in this case, we have 5 chart areas as 5 resources selected on the checked list box.

From the third resource, I add 300 as the minimum scroll value of the panel, so the size of the chart increases, and the chart areas do not look excessively different in height every time we add a chart area.

Chart view for 13 Resources:

enter image description here

Chart view for 18 Resources:

enter image description here

Chart view for 21 resources:

enter image description here

And finally, chart view for 26 or more resoures:

enter image description here

Code:

Auxiliar method to clone a chart area

    private ChartArea CloneChartArea(ChartArea chartArea, string resultName)
    {
        var result = new ChartArea();

        result.Name = resultName;

        result.AxisX.MajorTickMark.LineColor = chartArea.AxisX.MajorTickMark.LineColor;
        result.AxisY.MajorTickMark.LineColor = chartArea.AxisY.MajorTickMark.LineColor;

        result.AxisX.LabelStyle.Font = chartArea.AxisX.LabelStyle.Font;
        result.AxisY.LabelStyle.Font = chartArea.AxisY.LabelStyle.Font;

        result.AxisX.LabelStyle.ForeColor = chartArea.AxisX.LabelStyle.ForeColor;
        result.AxisY.LabelStyle.ForeColor = chartArea.AxisY.LabelStyle.ForeColor;

        /// The following lines allow us to paint multiple chart areas in one column 
        result.AlignWithChartArea = chartArea.Name;
        result.AlignmentStyle = AreaAlignmentStyles.Position;
        result.AlignmentOrientation = AreaAlignmentOrientations.Vertical;

        return result;
    }
    

Auxiliar method to set axis y label

    private ChartArea SetAxisLabelY(ChartArea chartArea, string ylabel, Color foreColor, float fontSize)
    {
        chartArea.AxisY.Title = ylabel;
        chartArea.AxisY.TitleAlignment = StringAlignment.Center;
        chartArea.AxisY.TitleFont = new Font("Century Gothic", fontSize, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
        chartArea.AxisY.TitleForeColor = foreColor;
        return chartArea;
    }

Main method to set chart values:

    private void SetChartValues(IEnumerable<IGrouping<int, ResourceDailyCalendar>> data)
    {
        while (chart1.Series.Any())
        {
            chart1.Series.RemoveAt(0);
            if (chart1.ChartAreas.Count > 1)
            {
                chart1.ChartAreas.RemoveAt(1);
            }
        }

        panel5.AutoScrollMinSize = new Size(0, 0);

        if (data != null && data.Count() > 0)
        {
            var resourcesNames = data.SelectMany(group => group).Select(element => element.Resource).Distinct().ToList();
            var chartAreaIndex = 1;
            foreach (var resourceName in resourcesNames)
            {
                var chartAreaName = string.Format("ChartArea{0}", chartAreaIndex);

                ChartArea chartArea = chart1.ChartAreas.Last();
                if (!chart1.ChartAreas.Any(ca => ca.Name.Equals(chartAreaName)))
                {
                    chartArea = CloneChartArea(chartArea, resultName: chartAreaName);
                    chart1.ChartAreas.Add(chartArea);
                    if (chartAreaIndex > 3)
                    {
                        var minScroll = panel5.AutoScrollMinSize;
                        if (minScroll.IsEmpty)
                        {
                            minScroll.Height = panel5.Size.Height;
                        }
                        minScroll.Height += 300;
                        panel5.AutoScrollMinSize = minScroll;
                    }
                }

                chartArea = SetAxisLabelY(chartArea, resourceName, Color.Yellow, 10F);

                var totalSerie = new Series()
                {
                    Name = $"{resourceName} - Total",
                    ChartArea = chartArea.Name,
                    ChartType = SeriesChartType.StackedColumn,
                    Color = Color.Black,
                    BorderWidth = 1,
                    BorderDashStyle = ChartDashStyle.Solid,
                    IsVisibleInLegend = false
                };

                var allowedSerie = new Series()
                {
                    Name = $"{resourceName} - Allowed",
                    ChartArea = chartArea.Name,
                    ChartType = SeriesChartType.StackedColumn,
                    Color = Color.Gray,
                    BorderWidth = 1,
                    BorderDashStyle = ChartDashStyle.Solid,
                    IsVisibleInLegend = false
                };

                var currentSerie = new Series()
                {
                    Name = $"{resourceName} - Current",
                    ChartArea = chartArea.Name,
                    ChartType = SeriesChartType.StackedColumn,
                    BorderWidth = 1,
                    BorderDashStyle = ChartDashStyle.Solid,
                    IsVisibleInLegend = false
                };

                var x = 0;
                var maxValue = 0.0;
                foreach (var group in data)
                {
                    string axisLabel;
                    if (group.Count() == 1) /// Agrupados por día
                    {
                        if (group.First().Resource != resourceName) continue;

                        axisLabel = group.First().Date.Value.ToShortDateString();
                    }
                    else
                    {
                        if (group.Count() > 1 && group.Count() < 8) /// Agrupados por semanas
                        {
                            axisLabel = group.First().YYYYWW.ToString();
                        }
                        else /// Agrupados por meses
                        {
                            axisLabel = group.First().YYYYMM.ToString();
                        }
                    }

                    var effectiveWorkingHours = group.Where(i => i.Resource == resourceName).Sum(i => i.EffectiveWorkingHours);
                    currentSerie.Points.AddXY(x, effectiveWorkingHours);
                    currentSerie.Points[x].AxisLabel = axisLabel;
                    maxValue = effectiveWorkingHours > maxValue ? effectiveWorkingHours : maxValue;

                    var workingHours = group.Where(i => i.Resource == resourceName).Sum(i => i.WorkingHours);
                    maxValue = workingHours > maxValue ? workingHours : maxValue;
                    workingHours -= effectiveWorkingHours;
                    allowedSerie.Points.AddXY(x, workingHours);
                    allowedSerie.Points[x].AxisLabel = axisLabel;

                    var periodTotalHours = group.Where(i => i.Resource == resourceName).Sum(i => i.PeriodTotalHours);
                    maxValue = periodTotalHours > maxValue ? periodTotalHours : maxValue;
                    periodTotalHours -= (workingHours + effectiveWorkingHours);
                    totalSerie.Points.AddXY(x, periodTotalHours);
                    totalSerie.Points[x].AxisLabel = axisLabel;

                    x++;
                }

                chart1.Series.Add(currentSerie);
                chart1.Series.Add(allowedSerie);
                chart1.Series.Add(totalSerie);

                chart1.ChartAreas.First(ca => ca.Name == chartArea.Name).AxisY.Maximum = maxValue * 1.1;

                chartAreaIndex++;
            }

            /// Resize de chart
            var currentHeight = 0;
            var chartAreasCounter = chart1.ChartAreas.Count();

            foreach (ChartArea ca in chart1.ChartAreas)
            {
                ca.AxisY.Minimum = 0;
                ca.Position.Height = 100 / chartAreasCounter;
                ca.Position.Y = currentHeight;
                ca.Position.X = 0;
                ca.Position.Width = 100;
                ca.AxisX.MaximumAutoSize = 5;
                currentHeight += 100 / chartAreasCounter;
            }

            chart1.ApplyPaletteColors();
            chart1.Update();

            System.Windows.Forms.Application.DoEvents();
        }
    }

Could anyone help me how to prevent this please?

Filburt
  • 17,626
  • 12
  • 64
  • 115
Jesus Hedo
  • 119
  • 1
  • 1
  • 10
  • I think you need to control the chartaeas' Positions in your code. Learn about ElementPositions! They are in % of the respective container. To stack 5 CAs in one column you could set them to (0,height/5 * i, 100, height/5). This allows no space for labels legends etc.. – TaW Apr 23 '21 at 12:50
  • I would appreciate it if you could be more specific with your answer. Are you referring to the "Position" property? – Jesus Hedo Apr 23 '21 at 13:38
  • 1
    Yes, indeed. [Example](https://stackoverflow.com/questions/43763361/c-sharp-mschart-charts-area-limits/43764417#43764417) – TaW Apr 23 '21 at 13:40
  • Nice, the property I should manage and I didn't was `InnerPlotPosition`, now all the chart areas are shown. However, the axis X labels still are getting away from the chart so when the number of chart areas are greater than 12 (for example) I must hide them. I suppose that's another question to do. Anyway thanks for your reply. – Jesus Hedo Apr 26 '21 at 07:43

0 Answers0