I created a custom Candlestick chart inherited from System.Windows.Forms.DataVisualization.Charting.Chart.
I have problems to retrieve the X and Y values of each DataPoint when mouse is over the area occupied by a Candlestick.
I tried the HitTest Method but it works only if mouse is over the Point.
Hope this screen helps:
This is the whole code of my custom chart:
public class MyChart : Chart
{
const int defaultZoomLevel = 2;
// Amount of Candles on the Range after zooming in/out
private int[] zoomLevels = new int[6] { 1500, 750, 450, 230, 120, 50 };
// Amount of Candles for the Chart Interval
private int[] intervalLevels = new int[6] { 100, 50, 20, 15, 10, 5 };
private int currentZoomLevel = defaultZoomLevel;
// List of Candles to show on the Chart--- Candle is a struct with the following properties: Open,Close,High,Low,Time
List<Candle> Candles;
// This method is called by another Class that request a new Chart
public void Initialize()
{
// Reset Current Zoom Level to default.
currentZoomLevel = defaultZoomLevel;
// Initialize Chart
InitializeChart();
this.ChartAreas[0].AxisX.ScaleView.Zoom(0, (zoomLevels[2] / 4));
this.ChartAreas[0].AxisX.ScaleView.Position = this.ChartAreas[0].AxisX.Maximum - (zoomLevels[defaultZoomLevel] / 4);
ScaleAxisY((int)this.ChartAreas[0].AxisX.ScaleView.ViewMinimum, (int)this.ChartAreas[0].AxisX.ScaleView.ViewMaximum);
}
private void ScaleAxisY(int start, int end)
{
double[] tempHighs = this.Series[0].Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[0]).ToArray();
double[] tempLows = this.Series[0].Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[1]).ToArray();
double ymin = (tempHighs.Length > 0) ? tempLows.Min() : this.Series[0].Points[this.Series[0].Points.Count - 1].YValues[0];
double ymax = (tempLows.Length > 0) ? tempHighs.Max() : this.Series[0].Points[this.Series[0].Points.Count - 1].YValues[1];
this.ChartAreas[0].AxisY.ScaleView.Position = ymin;
this.ChartAreas[0].AxisY.ScaleView.Size = (ymax - this.ChartAreas[0].AxisY.ScaleView.Position);
Update();
}
private void InitializeChart()
{
this.ChartAreas.Clear();
this.Series.Clear();
this.ChartAreas.Add(new ChartArea());
this.Series.Add(new Series("candles"));
// PROPERTIES
this.Series[0].ChartType = SeriesChartType.Candlestick;
this.Series[0].Color = Color.Green;
this.Series[0].XValueType = ChartValueType.DateTime;
this.Series[0].IsXValueIndexed = true;
this.Series[0].YValuesPerPoint = 4;
this.Series[0].CustomProperties = "MaxPixelPointWidth=10,PriceDownColor=Red, PriceUpColor=Green"; ;
this.Series[0].ChartType = SeriesChartType.Candlestick;
// POPULATE CHART
// The first Candle is the latest one so I'm adding them to chart in reverse order.
for (int i = Candles.Count - 1; i >= 0; i--)
{
var item = Candles[i];
this.Series[0].Points.AddXY(item.Time.ToOADate(), item.High, item.Low, item.Open, item.Close);
}
var minValue = this.Series[0].Points.Min(x => x.YValues[0]);
var maxValue = this.Series[0].Points.Max(x => x.YValues[1]);
this.ChartAreas[0].AxisY.Minimum = minValue;
this.ChartAreas[0].AxisY.Maximum = maxValue;
this.ChartAreas[0].CursorX.AutoScroll = true;
this.ChartAreas[0].AxisY.ScrollBar.Enabled = false;
this.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
this.ChartAreas[0].AxisX.ScaleView.SizeType = DateTimeIntervalType.Auto;
this.ChartAreas[0].AxisX.LabelStyle.Format = "d MMM yyyy HH:mm";
this.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
this.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
this.ChartAreas[0].AxisX.Interval = intervalLevels[defaultZoomLevel];
ChartAreas[0].RecalculateAxesScale();
}
}
I've tried PixelPositionToValue on X-Axis to get the DateTime value but it gives me the point Index rather than a DateTime value and it's not even correct.
I'm sure there are some errors on my code because the same method works when used to get the Y-Axis value.
I had a similar problem retrieving the PixelPosition on the X-Axis using a DateTime value (AxisX.ValueToPixelPosition) but I found a solution.
So how can I get X and Y values of a DataPoint when mouse is over the whole candle area?
Any tips will be very appreciated!
Note: I also have methods to scroll and zoom the chart and scale the Y-axis. Maybe they also need some changes.