c# ms chart how do I add a vertical line?

I have a chart control where I map out a line which is curved.  I want to add a few different vertical lines.  Basically I want to do something like new line(x=5)

How I'm currently drawing:

for (double i = currentPriceOfUnderlying * .5; i < currentPriceOfUnderlying * 1.5; i = i + .1)
{
          totalAtThisStrik = somefunction(i)
      chart1.Series["Series1"].Points.Add(new DataPoint(i, totalAtThisStrike));
}
jackjohnson44Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Robert SchuttSoftware EngineerCommented:
I've tried this a number of different ways, this is the cleanest I've come up with. A lot nicer could be to derive a new class from Chart and add this functionality to it. Maybe I missed a more obvious implementation like using StripLines (but for some reason, just a gut feeling, I didn't like that solution). So just to make sure that doing it this way offers something extra, I tried to draw something a little more fancy than a simple line...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Windows.Forms.DataVisualization.Charting;

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

        double currentPriceOfUnderlying = 5.4;

        double[] xlines = { 2, 3.4, 5, 6.7, 8, 9 };

        private void Form1_Load(object sender, EventArgs e) {
            double totalAtThisStrike;
            for (double i = currentPriceOfUnderlying * .5; i < currentPriceOfUnderlying * 1.5; i = i + .1) {
                totalAtThisStrike = somefunction(i);
                chart1.Series["Series1"].Points.Add(new DataPoint(i, totalAtThisStrike));
            }
            chart1.ChartAreas["ChartArea1"].AxisX.Interval = .1;

            chart1.Series["Series1"].ChartType = SeriesChartType.Line;
            chart1.Series["Series1"].BorderWidth = 3;
            chart1.Series["Series1"].MarkerStyle = MarkerStyle.Diamond;
            chart1.Series["Series1"].MarkerSize = 7;
            chart1.PostPaint += new EventHandler<ChartPaintEventArgs>(chart1_PostPaint);
        }

        void chart1_PostPaint(object sender, ChartPaintEventArgs e) {
            foreach (double xval in xlines) {
                PaintVerticalChartLine(e.Chart, e.ChartGraphics, xval);
            }
        }

        private void PaintVerticalChartLine(Chart chart, ChartGraphics chartGraphics, double xval) {

            // should be globals
            double xvalMin = currentPriceOfUnderlying * .5;
            double xvalMax = currentPriceOfUnderlying * 1.5;

            if (xvalMin <= xval && xvalMax >= xval) {
                double x = chart.ChartAreas["ChartArea1"].AxisX.ValueToPixelPosition(xval);
                double y0 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Minimum);
                double y1 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Maximum);

                int pointMax = chart.Series["Series1"].Points.Count - 1;
                int pointNum = (int)Math.Round((double)pointMax * (xval - xvalMin) / (xvalMax - xvalMin));
                double y2 = (int)chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.Series["Series1"].Points[pointNum].YValues[0]);

                chartGraphics.Graphics.DrawLine(new Pen(Color.Silver, 5), (float)x, (float)(y0 - 1), (float)x, (float)(y1 + 1));
                chartGraphics.Graphics.DrawLine(new Pen(Color.Red, 3), (float)x, (float)(y0 - 2), (float)x, (float)y2);
            }
        }

        private double somefunction(double i) {
            return 25 * Math.Sin(2 * Math.PI * i / currentPriceOfUnderlying);
        }
    }
}

Open in new window

capture new
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jackjohnson44Author Commented:
Thanks!
0
jackjohnson44Author Commented:
I don't actually understand what you did here.  Sorry for the delay.

I was looking to put in a vertical line.  Why is there a mention of xValMin, xValMax?  Why is my other variables relavent here like currentPriceOfUnderlying?


Can you please explain what you did?  

Thanks


        private void PaintVerticalChartLine(Chart chart, ChartGraphics chartGraphics, double xval)
        {
            double x = chart.ChartAreas["ChartArea1"].AxisX.ValueToPixelPosition(xval);
            double y0 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Minimum);
            double y1 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Maximum);

            int pointMax = chart.Series["Series1"].Points.Count - 1;
            int pointNum = (int) Math.Round((double) pointMax*(xval - xvalMin)/(xvalMax - xvalMin));
            double y2 = (int) chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.Series["Series1"].Points[pointNum].YValues[0]);

            chartGraphics.Graphics.DrawLine(new Pen(Color.Silver, 5), (float) x, (float) (y0 - 1), (float) x, (float) (y1 + 1));
            chartGraphics.Graphics.DrawLine(new Pen(Color.Red, 3), (float) x, (float) (y0 - 2), (float) x, (float) y2);
        }
0
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

jackjohnson44Author Commented:
Also, is there a way to call this without binding to an event?  I'd like to call it with parameters I can pass.  I am not sure how to access chartGraphics.
0
Robert SchuttSoftware EngineerCommented:
Well to start with the last question: that's the point, e.chartGraphics is only available in the PostPaint event. There may be a way but I haven't seen a clean way to do that.

In a previous solution I have set AxisX.Minimum and Maximum to the range needed to avoid having gaps left and right. In this solution I did it a bit different to let that part work the way it does by default. What stayed the same is that I used the Points array to determine the value based on the fact that you use a constant step in you x values. There's probably a better way for that using the chart methods (eliminating the need for defining min/max as well) but I was looking for a solution and came up with this.

What you want probably would take subclassing the Chart class and make a new method to paint a vertical line. It would still need to figure out where to draw the line exactly but maybe it would be easier to access the various min/max positions. It should be possible to clean up the current code for the purpose of not using min/max.
0
jackjohnson44Author Commented:
Thanks.  Can you please explain the code inside the if statement? I don't understand it at all, or why min and max are used at all.  Does that correspond to the size of my grid?

This is my first use of the Chart and I really don't get it at all.
0
Robert SchuttSoftware EngineerCommented:
Sure: the check on xval is done because an error would occur when trying to do the calculations I do later on with a value that lies outside the bounds of the chart.

This is because of the way I get to the y value needed. Note that this is only because I chose to do something 'fancy' i.e. show a red line up to the y value at that point inside the grey line which goes all the way up. So, to get the x value I do something which may not be needed at all (once more, sorry): calculate the index in the point array that is closest to the x value where the line needs to be drawn. This can be done with a simple linear equation because the points are evenly spaced on the x axis.

Note that I did all this because I was under the impression that you did have some more experience with Charts (if only from previous questions) and would like to see something spiffy instead of a solution that you could have gotten by googling. But in retrospect sorry about that, I should have tried to come up with a straightforward solution first.

One way to get rid of all that unnecessary complex stuff, if you need only the full line, is to use this instead:
        private void PaintVerticalChartLine(Chart chart, ChartGraphics chartGraphics, double xval) {
            double x = chart.ChartAreas["ChartArea1"].AxisX.ValueToPixelPosition(xval);
            double y0 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Minimum);
            double y1 = chart.ChartAreas["ChartArea1"].AxisY.ValueToPixelPosition(chart.ChartAreas["ChartArea1"].AxisY.Maximum);
            chartGraphics.Graphics.DrawLine(new Pen(Color.Silver, 5), (float)x, (float)(y0 - 1), (float)x, (float)(y1 + 1));
        }

Open in new window

You do still need to do this in a paint event because those methods (ValueToPixel) don't work otherwise. A downside is that the lines are drawn even when outside the bounds of the chart.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.