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:
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:
Chart view for 18 Resources:
Chart view for 21 resources:
And finally, chart view for 26 or more resoures:
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?