New to Telerik UI for WinForms? Download free 30-day trial

How to get CategoricalAxis value on mouse click in CandleStickSeries

Environment

Product Version Product Author
2021.1.223 RadChartView for WinForms Nadya Karaivanova

Description

Let's say that you have RadChartView with CandleStickSeries that plots its data on the DateTimeCategorical axis for the horizontal axis and Linear axis for the vertical axis. This article will demonstrate how you can get the DateTime value from the horizontal axis when there is an interaction with the mouse, for example when the user clicks clicks with the mouse.

how-to-get-categoricalaxis-value-on-mouse-click-in-candlestickseries

Solution

In order to achieve this, it would be helpful to use an "onePixelTime" variable that shows how many ticks a single pixel of the chart represents. It can also be helpful when the view is zoomed to a particular date range. Then, in the MouseDown event, the exact location is calculated. Please refer to the following example:

public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
    CandlestickSeries candlestickSeries;
    public RadForm1()
    {
        InitializeComponent();
        this.radChartView1.MouseDown += this.RadChartView1_MouseDown;
        candlestickSeries = new CandlestickSeries();
        candlestickSeries.DataPoints.Add(new OhlcDataPoint(10, 11, 7, 8, DateTime.Now));
        candlestickSeries.DataPoints.Add(new OhlcDataPoint(8, 9, 5, 9, DateTime.Now.AddDays(1)));
        candlestickSeries.DataPoints.Add(new OhlcDataPoint(12, 12, 9, 10, DateTime.Now.AddDays(2)));
        candlestickSeries.DataPoints.Add(new OhlcDataPoint(7, 10, 6, 9, DateTime.Now.AddDays(3)));
        this.radChartView1.Series.Add(candlestickSeries);
    }

    // Represents how many ticks a single pixel of the chart represents
    double onePixelTime = 0;
    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        var first = (OhlcDataPoint)candlestickSeries.DataPoints[0];
        var last = (OhlcDataPoint)candlestickSeries.DataPoints[candlestickSeries.DataPoints.Count - 1];
        TimeSpan span = (DateTime)last.Category - (DateTime)first.Category;

        double totalWidth = last.LayoutSlot.X + last.LayoutSlot.Width / 2 - first.LayoutSlot.X - first.LayoutSlot.Width / 2;
        this.onePixelTime = span.Ticks / totalWidth;
    }

    private void RadChartView1_MouseDown(object sender, MouseEventArgs e)
    {
        IChartView view = this.radChartView1.View;
        var firstDataPoint = (OhlcDataPoint)candlestickSeries.DataPoints[0];
        var offset = this.radChartView1.Area.View.Viewport.X + firstDataPoint.LayoutSlot.X + firstDataPoint.LayoutSlot.Width / 2;

        double location = e.Location.X - offset - view.PlotOriginX;
        long ticks = (long)(location * this.onePixelTime / view.ZoomWidth);
        TimeSpan span = TimeSpan.FromTicks(ticks);

        DateTime startDate = (DateTime)firstDataPoint.Category;
        DateTime clickedDate = startDate.Add(span);
        Console.WriteLine(clickedDate);
    }
}    

Public Partial Class RadForm1
    Inherits Telerik.WinControls.UI.RadForm
    Private candlestickSeries As CandlestickSeries

    Public Sub New()
        InitializeComponent()
        AddHandler Me.radChartView1.MouseDown, AddressOf Me.RadChartView1_MouseDown
        candlestickSeries = New CandlestickSeries()
        candlestickSeries.DataPoints.Add(New OhlcDataPoint(10, 11, 7, 8, DateTime.Now))
        candlestickSeries.DataPoints.Add(New OhlcDataPoint(8, 9, 5, 9, DateTime.Now.AddDays(1)))
        candlestickSeries.DataPoints.Add(New OhlcDataPoint(12, 12, 9, 10, DateTime.Now.AddDays(2)))
        candlestickSeries.DataPoints.Add(New OhlcDataPoint(7, 10, 6, 9, DateTime.Now.AddDays(3)))
        Me.radChartView1.Series.Add(candlestickSeries)
    End Sub

    ' Represents how many ticks a single pixel of the chart represents
    Private onePixelTime As Double = 0
    Protected Overrides Sub OnShown(ByVal e As EventArgs)
        MyBase.OnShown(e)
        Dim first = CType(candlestickSeries.DataPoints(0), OhlcDataPoint)
        Dim last = CType(candlestickSeries.DataPoints(candlestickSeries.DataPoints.Count - 1), OhlcDataPoint)
        Dim span As TimeSpan = CType(last.Category, DateTime) - CType(first.Category, DateTime)
        Dim totalWidth As Double = last.LayoutSlot.X + last.LayoutSlot.Width / 2 - first.LayoutSlot.X - first.LayoutSlot.Width / 2
        Me.onePixelTime = span.Ticks / totalWidth
    End Sub

    Private Sub RadChartView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        Dim view As IChartView = Me.radChartView1.View
        Dim firstDataPoint = CType(candlestickSeries.DataPoints(0), OhlcDataPoint)
        Dim offset = Me.radChartView1.Area.View.Viewport.X + firstDataPoint.LayoutSlot.X + firstDataPoint.LayoutSlot.Width / 2
        Dim location As Double = e.Location.X - offset - view.PlotOriginX
        Dim ticks As Long = CLng((location * Me.onePixelTime / view.ZoomWidth))
        Dim span As TimeSpan = TimeSpan.FromTicks(ticks)
        Dim startDate As DateTime = CType(firstDataPoint.Category, DateTime)
        Dim clickedDate As DateTime = startDate.Add(span)
        Console.WriteLine(clickedDate)
    End Sub
End Class

In this article