Link to home
Start Free TrialLog in
Avatar of jackjohnson44
jackjohnson44

asked on

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));
}
ASKER CERTIFIED SOLUTION
Avatar of Robert Schutt
Robert Schutt
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jackjohnson44
jackjohnson44

ASKER

Thanks!
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);
        }
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.
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.
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.
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.