The solution that worked for me.
First, add the annotation as usual. The key is to make it invisible and then draw it manually in the Chart.PostPaint event.
var text = new RectangleAnnotation();
text.ClipToChartArea = chart.ChartAreas[0].Name;
text.Text = "Title";
text.AxisX = chart.AxisX;
text.AxisY = chart.AxisY;
text.X = value;
text.Y = chart.AxisY.Maximum;
text.BackColor = chart.BaseSettings.ColorStorage["First"][1]; // Use your colors
text.LineColor = chart.BaseSettings.ColorStorage["First"][1];
text.ForeColor = Color.White;
text.Visible = false; // <- Hide the annotation.
chart.graph.Annotations.Add(text);
text.ResizeToContent();
Secondly, manually draw the text in Chart.PostPaint.
private static void ChartPostPaint(object sender, ChartPaintEventArgs e)
{
var chart = (Chart)sender;
foreach (var annotation in chart.Annotations)
{
var text = annotation as RectangleAnnotation;
if (text == null || text.Visible)
{
/* Skip all other irrelevant annotations and those which are visible. */
continue;
}
var g = e.ChartGraphics.Graphics;
var m = g.MeasureString(text.Text, text.Font);
/* Convert the chart coordinates to the absolute values. */
float x = (float)e.ChartGraphics.GetPositionFromAxis(text.ClipToChartArea, AxisName.X, text.X);
float y = (float)e.ChartGraphics.GetPositionFromAxis(text.ClipToChartArea, AxisName.Y, text.Y);
float w = m.Height;
float h = m.Width;
var p = e.ChartGraphics.GetAbsolutePoint(new PointF(x, y));
using (var bg = new SolidBrush(text.BackColor))
using (var fc = new SolidBrush(text.ForeColor))
{
g.FillRectangle(bg, p.X - m.Height, p.Y, w, h);
/* Rotate the surface by 270 degrees around the text. */
var dx = p.X - (m.Height / 2f);
var dy = p.Y + (m.Height / 2f);
g.TranslateTransform(dx, dy);
g.RotateTransform(270);
g.TranslateTransform(-dx, -dy);
/* Draw the text as usual */
g.DrawString(text.Text, text.Font, fc, p.X - m.Width, p.Y + 1);
/* And rotate it back. */
g.ResetTransform();
}
}
}
