I would like to get the Y Value for a series corresponding to the X position of a ChartArea that the user has clicked-upon.
I have tried to capture the X position o
First convert the mouse click position to a relative position:
x= 100.0 * e.X / chart.Width
Then convert relative position to axis position:
double xMin= axis.Minimum;
double xMax= axis.Maximum;
double pMin= axis.GetPosition(xMin);
double pMax= axis.GetPosition(xMax);
xx= (x-pMin) * (xMax-xMin) / (pMax-pMin) + xMin;
Then use the axis position to probe the series (eg interpolate or nearest point as you like)
As for chart.ChartAreas[0].CursorX: A Chart Cursor
is an object created by and used for zooming and which then
Represents a horizontal or vertical line that defines a position along an axis.
So it has not much to do with the mouse cursor and is not valid when not zooming or (when zooming is disabled) for selecting.
There are a few options you have; unfortunately none are both simple and exactly what you asked for.
One simple thing is to use the HitTest
for Charts
:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
HitTestResult hit = chart1.HitTest(e.X, e.Y);
if (hit.PointIndex >= 0)
infoLabel.Text = "Over DataPoint No " + hit.PointIndex;
}
This is simple and safe but will work only when the cursor is actually over a DataPoint
. How well it suits you may depend on the ChartType
; Very well for Columns
or Bars
but not so well for Points
or Bubbles
..
And you could call PixelPositionToValue
:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
var xv = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X);
var yv = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y);
infoLabel.Text = "x = " + xv + " y =" + yv;
}
In theory this is only safe to call from one of the Paint
events but in practice it seems to work fine when called from user interactions as well. (If you run into problems you could do a dummy call on one of the Paint
events and abort it with a flag after pulling the value(s) you want; the example does a lot more than what you need, but I doubt it will be necessary at all..)
However it will only bring back the Values
according to the axis, not the nearest DataPoint
. If you really need to get at the actual DataPoint
you would then have to do a search over the Points
of your Series
..:
Series S = chart1.Series[0]; // short reference
DataPoint pPrev = S.Points.Select(x => x)
.Where(x => x.XValue >= xv)
.DefaultIfEmpty(S.Points.First()).First();
DataPoint pNext = S.Points.Select(x => x)
.Where(x => x.XValue <= xv)
.DefaultIfEmpty(S.Points.Last()).Last();
This should bring up the previous and next DataPoint
. It is up to you to decide which one to use..
You'll need a MouseClick-Handler for your chart control instead of a normal Click-Handler, because of the "MouseEventArgs":
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
//check where you clicked, returns different information like the clicked series name and the index of the clicked point
HitTestResult clicked = chart1.HitTest(e.X, e.Y);
//this is how you get your y-Value
double yValue = chart1.Series[clicked.Series.Name].Points[clicked.PointIndex].YValues[0];
}