chart x-axis numbering

2019-02-27 18:56发布

问题:

I am using WinForms chart to visualize some data. I want x-axis gridlines at points specified by me. Please take a look at the following example.

public partial class Form1: Form
{
    public Form1()
    {
        InitializeComponent();            
        AddPoints();
    }

    public void AddPoints()
    {
        for (int i = 0; i <= 100; i++)
            chart1.Series[0].Points.AddXY(i, i);
    }
}

In the chart you can see the grid lines for X-Axis appears at 19,39,59,79 and 99. But I want it in 0,15,45,65,90,100. You can clearly see the interval is not the same. So setting the interval is of no use. Is it possible to have grid lines in my own specified point?

回答1:

This is not possible with GridLines as they will always be drawn at the fixed Interval spacing. Here is an example of working around by drawing the lines in an xxxPaint event..

First we declare a list of stop values for the GridLines we want:

List<double> stops = new List<double>();

Then we prepare the chart:

AddPoints();

ChartArea ca = chart1.ChartAreas[0];
ca.AxisX.Minimum = 0;  // optional
ca.AxisX.MajorGrid.Enabled = false;
ca.AxisX.MajorTickMark.Enabled = false;
ca.AxisX.LabelStyle.Enabled = false;

stops.AddRange(new[] { 0, 15, 45, 50.5, 65, 90, 100 });

Note that I have added one extra value (50.5) to show how we can draw GridLines even where not DataPoints are!

Then we code the PostPaint event:

private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    Graphics g = e.ChartGraphics.Graphics;
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;

    ChartArea ca = chart1.ChartAreas[0];

    Font font = ca.AxisX.LabelStyle.Font;
    Color col = ca.AxisX.MajorGrid.LineColor;
    int padding = 10; // pad the labels from the axis

    int y0 = (int)ca.AxisY.ValueToPixelPosition(ca.AxisY.Minimum);
    int y1 = (int)ca.AxisY.ValueToPixelPosition(ca.AxisY.Maximum);

    foreach (int sx  in stops)
    {
        int x = (int)ca.AxisX.ValueToPixelPosition(sx);

        using (Pen pen = new Pen(col))
            g.DrawLine(pen, x, y0, x, y1);

        string s =  sx + "";
        if (ca.AxisX.LabelStyle.Format != "") 
            s = string.Format(ca.AxisX.LabelStyle.Format, s);

        SizeF sz = g.MeasureString(s, font, 999);
        g.DrawString(s, font, Brushes.Black, (int)(x - sz.Width / 2) , y0 + padding);
}

This is the result:

Note that most of the code in the PostPaint event is just preparation; the two actual drawing calls for the lines and the labels are ordinary GDI+ methods..

Note that I have added DataPoint labels to every 10th point in the loop to show where we are:

chart1.Series[0].Points.AddXY(i, i);
if (i%10 == 0) chart1.Series[0].Points[i].Label = "#VAL / #VALY";