Ra3IDeN Ra3IDeN - 1 month ago 10
C# Question

How to set chart title above y-axis?

I have been experimenting with charts and so far I got this experimental code:

static void Main(string[] args)
{
Random rnd = new Random();

Chart thisChart = new Chart();

thisChart.Height = 400;
thisChart.Width = 500;
thisChart.BackColor = SystemColors.Window;
thisChart.Palette = ChartColorPalette.EarthTones;
thisChart.Titles.Add("Test");
thisChart.Visible = true;

ChartArea ca = new ChartArea();
ca.Name = "Default";
ca.BackColor = Color.White;
ca.BorderColor = Color.FromArgb(26, 59, 105);
ca.BorderWidth = 0;
ca.BorderDashStyle = ChartDashStyle.Solid;
ca.AxisX = new Axis();
ca.AxisY = new Axis();
thisChart.ChartAreas.Add(ca);

Series series = thisChart.Series.Add("Default");
series.ChartType = SeriesChartType.Spline;
series.ChartArea = "Default";
series.Points.AddXY("1", 20);
series.Points.AddXY("2", 25);
series.Points.AddXY("3", 30);
series.Points.AddXY("4", 35);
series.Points.AddXY("5", 40);
series.Points.AddXY("6", 45);

//SetPosition for multiple Y-axis labels
thisChart.ChartAreas["Default"].Position = new ElementPosition(25, 10, 68, 85);
thisChart.ChartAreas["Default"].InnerPlotPosition = new ElementPosition(10, 0, 90, 80);

// Create extra Y axis for second and third series
Series series2 = thisChart.Series.Add("Series2");
series2.ChartType = SeriesChartType.Spline;
series2.ChartArea = "Default";
series2.Points.AddXY("1", 50);
series2.Points.AddXY("2", 55);
series2.Points.AddXY("3", 60);
series2.Points.AddXY("4", 70);
series2.Points.AddXY("5", 75);
series2.Points.AddXY("6", 80);
//series2.Legend = "Default";

thisChart.Series["Series2"].ChartArea = "Default";
CreateYAxis(thisChart, thisChart.ChartAreas["Default"], thisChart.Series["Series2"], 13, 8);

// Create extra X axis for second and third series
Series series3 = thisChart.Series.Add("Series3");
series3.ChartType = SeriesChartType.Spline;
series3.ChartArea = "Default";
series3.Points.AddXY("1,5", 75);
series3.Points.AddXY("2,5", 175);
series3.Points.AddXY("3,5", 300);
series3.Points.AddXY("4,5", 75);
series3.Points.AddXY("5,5", 150);
series3.Points.AddXY("6,6", 125);

thisChart.Series["Series3"].ChartArea = "Default";
CreateXAxis(thisChart, thisChart.ChartAreas["Default"], thisChart.Series["Series3"], -10, 8);

//thisChart.DataBind();
thisChart.SaveImage(@"C:\Temp\TestChart.png", ChartImageFormat.Png);

}

private static void CreateYAxis(Chart chart, ChartArea area, Series series, float axisOffset, float labelsSize)
{
// Create new chart area for original series
ChartArea areaSeries = chart.ChartAreas.Add("ChartArea_" + series.Name);
areaSeries.BackColor = Color.Transparent;
areaSeries.BorderColor = Color.Transparent;
areaSeries.Position.FromRectangleF(area.Position.ToRectangleF());
areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF());
areaSeries.AxisX.MajorGrid.Enabled = false;
areaSeries.AxisX.MajorTickMark.Enabled = false;
areaSeries.AxisX.LabelStyle.Enabled = false;
areaSeries.AxisY.MajorGrid.Enabled = false;
areaSeries.AxisY.MajorTickMark.Enabled = false;
areaSeries.AxisY.LabelStyle.Enabled = false;
areaSeries.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero;
areaSeries.AxisY.TitleAlignment = StringAlignment.Far;
areaSeries.AxisY.TextOrientation = TextOrientation.Horizontal;
areaSeries.AxisY.Title = "Y-axis Title1";
areaSeries.AxisY.TitleForeColor = Color.Blue;
areaSeries.AxisY.TitleFont = new Font("Tahoma", 7, FontStyle.Bold);
areaSeries.AxisY.Maximum = 300;


series.ChartArea = areaSeries.Name;

// Create new chart area for axis
ChartArea areaAxis = chart.ChartAreas.Add("AxisY_" + series.ChartArea);
areaAxis.BackColor = Color.Transparent;
areaAxis.BorderColor = Color.Transparent;
areaAxis.Position.FromRectangleF(chart.ChartAreas[series.ChartArea].Position.ToRectangleF());
areaAxis.InnerPlotPosition.FromRectangleF(chart.ChartAreas[series.ChartArea].InnerPlotPosition.ToRectangleF());
areaAxis.AxisY.TitleAlignment = StringAlignment.Center;
areaAxis.AxisY.Title = "Y-axis Title";
areaAxis.AxisY.TitleForeColor = Color.Blue;
areaAxis.AxisY.TitleFont = new Font("Tahoma", 7, FontStyle.Bold);
areaAxis.AxisY.TitleAlignment = StringAlignment.Far;
areaAxis.AxisY.TextOrientation = TextOrientation.Horizontal;
areaAxis.AxisY.Maximum = 200;


// Create a copy of specified series
Series seriesCopy = chart.Series.Add(series.Name + "_Copy");
seriesCopy.ChartType = series.ChartType;
foreach (DataPoint point in series.Points)
{
seriesCopy.Points.AddXY(point.XValue, point.YValues[0]);
}

// Hide copied series
seriesCopy.IsVisibleInLegend = false;
seriesCopy.Color = Color.Transparent;
seriesCopy.BorderColor = Color.Transparent;
seriesCopy.ChartArea = areaAxis.Name;

// Disable drid lines & tickmarks
areaAxis.AxisX.LineWidth = 0;
areaAxis.AxisX.MajorGrid.Enabled = false;
areaAxis.AxisX.MajorTickMark.Enabled = false;
areaAxis.AxisX.LabelStyle.Enabled = false;
areaAxis.AxisY.MajorGrid.Enabled = false;
areaAxis.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero;
areaAxis.AxisY.LabelStyle.Font = area.AxisY.LabelStyle.Font;

// Adjust area position
areaAxis.Position.X -= axisOffset;
areaAxis.InnerPlotPosition.X += labelsSize;

}

private static void CreateXAxis(Chart chart, ChartArea area, Series series, float axisOffset, float labelsSize)
{
// Create new chart area for original series
ChartArea areaSeries = chart.ChartAreas.Add("ChartArea_" + series.Name);
areaSeries.BackColor = Color.Transparent;
areaSeries.BorderColor = Color.Transparent;
areaSeries.Position.FromRectangleF(area.Position.ToRectangleF());
areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF());

areaSeries.AxisY.MajorGrid.Enabled = false;
areaSeries.AxisY.MajorTickMark.Enabled = false;
areaSeries.AxisY.LabelStyle.Enabled = false;

areaSeries.AxisX.MajorGrid.Enabled = false;
areaSeries.AxisX.MajorTickMark.Enabled = false;
areaSeries.AxisX.LabelStyle.Enabled = false;
areaSeries.AxisX.IsStartedFromZero = area.AxisX.IsStartedFromZero;

series.ChartArea = areaSeries.Name;

// Create new chart area for axis
ChartArea areaAxis = chart.ChartAreas.Add("AxisX_" + series.ChartArea);
areaAxis.BackColor = Color.Transparent;
areaAxis.BorderColor = Color.Transparent;
areaAxis.Position.FromRectangleF(chart.ChartAreas[series.ChartArea].Position.ToRectangleF());
areaAxis.InnerPlotPosition.FromRectangleF(chart.ChartAreas[series.ChartArea].InnerPlotPosition.ToRectangleF());



// Create a copy of specified series
Series seriesCopy = chart.Series.Add(series.Name + "_Copy");
seriesCopy.ChartType = series.ChartType;
foreach (DataPoint point in series.Points)
{
seriesCopy.Points.AddXY(point.XValue, point.YValues[0]);
}

// Hide copied series
seriesCopy.IsVisibleInLegend = false;
seriesCopy.Color = Color.Transparent;
seriesCopy.BorderColor = Color.Transparent;
seriesCopy.ChartArea = areaAxis.Name;

// Disable drid lines & tickmarks
areaAxis.AxisY.LineWidth = 0;
areaAxis.AxisY.MajorGrid.Enabled = false;
areaAxis.AxisY.MajorTickMark.Enabled = false;
areaAxis.AxisY.LabelStyle.Enabled = false;

areaAxis.AxisX.MajorGrid.Enabled = false;
//areaAxis.AxisX.IntervalOffset = Convert.ToDouble("0,5");
areaAxis.AxisX.IsStartedFromZero = area.AxisX.IsStartedFromZero;
areaAxis.AxisX.LabelStyle.Font = area.AxisX.LabelStyle.Font;

areaAxis.AxisX.CustomLabels.Add(0, 1, "0.5");
areaAxis.AxisX.CustomLabels.Add(1, 2, "1.5");
areaAxis.AxisX.CustomLabels.Add(2, 3, "2.5");
areaAxis.AxisX.CustomLabels.Add(3, 4, "3.5");
areaAxis.AxisX.CustomLabels.Add(4, 5, "4.5");
areaAxis.AxisX.CustomLabels.Add(5, 6, "5.5");
areaAxis.AxisX.CustomLabels.Add(6, 7, "6.5");

// Adjust area position
areaAxis.Position.Y -= axisOffset;
areaAxis.InnerPlotPosition.Y += labelsSize;

}


This produces the following result:

enter image description here

PROBLEM:

I can not figure out how to make it so that the title aligns itself above the respective y-axis, any ideas?

TaW TaW
Answer Source

I don't think you do that.

Afaik the recommended workaround is adding more chart Titles.

You can style them as usual and to move them on top of a axis you can align them to the top left of the respective Chartearea.InnerPlotPosition:

ChartArea ca1 = thisChart.ChartAreas[0];
RectangleF rip1 = ca1.InnerPlotPosition.ToRectangleF();
Title ty1 = thisChart.Titles.Add("ty1");
ty1.Text = "Y-Axis 1\nTitle";
ty1.ForeColor = Color.DarkSlateBlue;
ty1.Position.X = rip1.Left;
ty1.Position.Y = rip1.Y;

Make sure to have enough space at the top of the chart for the titles..

enter image description here

Do note that the values of all ElementPositions, including InnerPlotPosition are in percent of the respective containers, i.e. of the ChartArea for the InnerPlotPosition and of the Chart for the ChartArea..