Here is a variation using the PostPaint
event:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
if (chart1.Series[0].Points.Count <= 0) return;
Graphics g = e.ChartGraphics.Graphics;
ChartArea ca = chart1.ChartAreas[0];
Rectangle rip = Rectangle.Round(InnerPlotPositionClientRectangle(chart1, ca));
StringFormat fmt = new StringFormat()
{ Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
int cols = chart1.Series[0].Points.Count;
int sCount = chart1.Series.Count;
int w = rip.Width / (cols + 1); // there is ca. 1/2 column gap to the sides
for (int i = 0; i < cols; i++)
{
List<string> s = (List<string>)(chart1.Series[0].Points[i].Tag);
for (int j = 0; j < s.Count; j++)
{
// change magic numbers with your font!
Rectangle r = new Rectangle(rip.Left + i * w + w / 2,
rip.Bottom + 5 + 25 * j, w, 25);
// 1st row: header, 2nd row sum, rest moved up by and reversed
using (SolidBrush brush = new SolidBrush(j == 0 ? Color.Transparent
: j == 1 ? Color.Gray : chart1.Series[sCount + 1 - j].Color))
g.FillRectangle(brush, r);
g.DrawRectangle(Pens.White, r);
g.DrawString(s[j], ca.AxisX.LabelStyle.Font, Brushes.White, r, fmt);
}
}
}
It uses the same routine to collect the label strings, but instead of setting the AxisLabels
it adds them to the Tags
of the DataPoints
:
string l = months[i] + "\n" + sum + label;
chart.Series[0].Points[i].Tag = l.Split('\n').ToList();
The Chart styling almost takes the largest part of the code:
chart.BackColor = Color.DarkSlateGray;
ChartArea ca = chart.ChartAreas[0];
chart.Legends[0].Alignment = StringAlignment.Center;
chart.Legends[0].Docking = Docking.Top;
chart.Legends[0].BackColor = chart.BackColor;
chart.Legends[0].ForeColor = Color.White;
Legend L = chart.Legends[0];
L.CustomItems.Add(Color.Silver, "Sum");
ca.BackColor = Color.LightSteelBlue;
ca.Position = new ElementPosition(2, 8, 93, 70); // make room
ca.Area3DStyle.Enable3D = true;
ca.Area3DStyle.PointDepth = 25;
ca.Area3DStyle.WallWidth = 0;
ca.AxisX.MajorGrid.Enabled = false;
ca.AxisY.MajorGrid.LineColor = Color.White;
ca.AxisY.LineColor = Color.White;
ca.AxisY.LabelStyle.ForeColor = Color.White;
ca.AxisY.MajorTickMark.LineColor = Color.White;
ca.AxisX.LabelStyle.Enabled = false;
ca.AxisX.LineColor = Color.White;
ca.AxisX.MajorTickMark.Enabled = false;
After creating the Series
with theit Colors
you need to apply them, so they can be accessed in code:
chart1.ApplyPaletteColors();
The nice rounded columns of a Series
s are created by a CustomProperty
s.SetCustomProperty("DrawingStyle", "Cylinder");
Some more details:
chart.Series[1].Color = Color.Crimson;
chart.Series[0].LegendText = "Hobbits";
..
Update: You need to include two functions InnerPlotPositionClientRectangle
and ChartAreaClientRectangle
from some of my other posts, like here or here!
To make this work in ASP you hook up the event in the PageLoad
:
chart1.PostPaint += new EventHandler<ChartPaintEventArgs>(chart1_PostPaint);