Chart for .NET / User's Guide / Interactivity / Hit Testing

In This Topic
    Hit Testing
    In This Topic
    The ability to determine the chart object at given window coordinates is an essential functionality build in Nevron Chart for Windows Forms. This feature is called "hit testing" and allows you to build advanced interactive applications.

    You perform hit testing by calling the HitTest function of the NChartControl class. It accepts two parameters specifying a point in window coordinates. The function returns an object of type NHitTestResult containing information about the underlying chart object. The following code for example intercepts the mouse click event and obtains a NHitTestResult object for the chart object laying under the mouse:

    C#
    Copy Code
    private void Form_Load(object sender, System.EventArgs e)
    {
     chartControl.MouseDown += new System.Windows.Forms.MouseEventHandler(OnMouseDown);
    }
    
    .....
    
    public void OnMouseDown(object sender, MouseEventArgs e)
    {
     NHitTestResult hitTestResult = chartControl.HitTest(e.X, e.Y);
    
     if (hitTestResult.ChartElement == ChartElement.ControlBackground)
     {
      // the user clicked on the chart control background.
     }
    }
    
    Visual Basic
    Copy Code
    Private Sub NMouseEventsUC_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
     AddHandler chartControl.MouseDown, AddressOf chartControl_MouseDown
    End Sub 'NMouseEventsUC_Load
    
    .......
    
    Private Sub chartControl_MouseDown(ByVal sender As Object, ByVal e As System.EventArgs)
     Dim hitTestResult As NHitTestResult = chartControl.HitTest(e.X, e.Y)
    
     if hitTestResult.ChartElement = ChartElement.ControlBackground then
      ' the user clicked on the chart control background.
     end if
    End Sub
    

    The most important property of the NHitTestResult object is the ChartElement property. It describes the type of the chart element at the given window coordinates. Depending on the chart element type some of the properties of the NHitTestResult referencing objects may be null (Nothing in VB .NET), similarly properties specifying indexes in some of the chart collections may be -1. The following table shows how the properties depend on the ChartElement property:

    Property Description Valid for chart elements
    Object A refence to a chart element. Valid for all chart elements except ChartElement.Nothing.
    Chart Returns a reference to the NChart object containing the located object.

    Valid when the ChartElement is contained within a chart (DataPoint, SurfaceDataPoint, Axis, AxisStripe, AxisConstLine, Axis, ChartWall etc.)

    ChartWall Returns a reference to a NChartWall object. Valid only when ChartElement is set to ChartWall.
    Series Returns a reference to the NSeriesBase object containing the located data item. Valid when ChartElement is ChartElement.SurfaceDataPoint or ChartElement.DataPoint.
    DataPointIndex Returns the index of the data point in the NSeries Values collection. Valid only when ChartElement is set to DataPoint.
    Axis Returns a reference to a NAxis object. Valid when ChartElement is Axis or AxisStripe, AxisConstLine or AxisCustomLabel.
    AxisStripe Returns a reference to a NAxisStripe object. Valid only when ChartElement is set to AxisStripe.
    Legend Returns a reference to a NLegend object Valid only when ChertElement is set to Legend, LegendDataItem, LegendHeader or LegendFooter.
    LegendDataItem Returns a reference to NLegendItemCellData object. Valid only when ChartElement is set to LegendDataItem.
    Label Returns a reference to a NLabel object. Valid only when ChartElement is set to Label.
    Watermark Returns a reference to a NWatermark object. Valid only when ChartElement is set to Watermark.

    Now lets see how this works in practice. The following example creates an interactive pie chart that allows the user to click on the pie slices. When a pie is clicked it will be detached from the pie center:

    C#
    Copy Code
    private void Form1_Load(object sender, System.EventArgs e)
    {
     chartControl.Charts.Clear();
     NPieChart pieChart = new NPieChart();
     chartControl.Charts.Add(pieChart);
    
     // create a pie series
     NPieSeries pie = (NPieSeries)pieChart.Series.Add(SeriesType.Pie);
    
     // add some data
     pie.AddDataPoint(new NDataPoint(12, "Cars", new NColorFillStyle(Color.FromArgb(56, 89, 150))));
     pie.AddDataPoint(new NDataPoint(42, "Trains", new NColorFillStyle(Color.DarkGreen)));
     pie.AddDataPoint(new NDataPoint(56, "Airplanes", new NColorFillStyle(Color.DarkGoldenrod)));
     pie.AddDataPoint(new NDataPoint(23, "Buses", new NColorFillStyle(Color.DarkRed)));
    
     // set pie detachments to zero
     for(int i = 0; i < pie.Values.Count; i++)
     {
      pie.Detachments.Add(0);
     }
    
     // subscribe for mouse down
     chartControl.MouseDown += new MouseEventHandler(ChartControl_MouseDown);
     chartControl.Refresh();
    }
    
    private void ChartControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
     if (e.Button != MouseButtons.Left)
      return;
    
     // perform hit test
     NHitTestResult hitTestResult = chartControl.HitTest(e.X, e.Y);
    
     // if this is a data point (pie slice) = detach it
     if (hitTestResult.ChartElement == ChartElement.DataPoint)
     {
      NPieSeries pie = hitTestResult.Series as NPieSeries;
      // remove detachments
      for (int i = 0; i < pie.Detachments.Count; i++)
      {
           pie.Detachments[i] = 0.0f;
      }
    
      // detach current slice
      pie.Detachments[hitTestResult.DataPointIndex] = 5.0f;
      chartControl.Refresh();
     }
    }
    
    Visual Basic
    Copy Code
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim chart As New NPieChart
        chartControl.Charts.Clear()
        chartControl.Charts.Add(chart)
    
        ' create a pie series
        Dim pie As NPieSeries = chart.Series.Add(SeriesType.Pie)
    
        ' add some data
        pie.AddDataPoint(New NDataPoint(12, "Cars", New NColorFillStyle(Color.FromArgb(56, 89, 150))))
        pie.AddDataPoint(New NDataPoint(42, "Trains", New NColorFillStyle(Color.DarkGreen)))
        pie.AddDataPoint(New NDataPoint(56, "Airplanes", New NColorFillStyle(Color.DarkGoldenrod)))
        pie.AddDataPoint(New NDataPoint(23, "Buses", New NColorFillStyle(Color.DarkRed)))
    
        ' set pie detachments to zero
        For i As Integer = 0 To pie.Values.Count - 1
            pie.Detachments.Add(0)
        Next i
    
        ' subscribe for mouse down
        AddHandler chartControl.MouseDown, AddressOf ChartControl_MouseDown
        chartControl.Refresh()
    End Sub
    
    Private Sub ChartControl_MouseDown(ByVal sender As Object, ByVal e As 
    System.Windows.Forms.MouseEventArgs)
        If Not (e.Button = MouseButtons.Left) Then
            Return
        End If
    
        ' perform hit test
        Dim hitTestResult As NHitTestResult = chartControl.HitTest(e.X, e.Y)
    
        ' if this is a data point (pie slice) = detach it
        If hitTestResult.ChartElement = ChartElement.DataPoint Then
            Dim pie As NPieSeries = CType(hitTestResult.Series, NPieSeries)
    
            ' remove detachments
            For i As Integer = 0 To pie.Detachments.Count - 1
                pie.Detachments(i) = 0.0
            Next i
    
            ' detach current slice
            pie.Detachments(hitTestResult.DataPointIndex) = 5.0
            chartControl.Refresh()
        End If
    End Sub
    

    Now lets investigate what happens in ChartControl_MouseDown function. The code first checks whether the user clicked on a data point object - if not it does not do anything. If yes it obtains a reference to the NPieSeries collection by using the properties in the NHitTest result object:

    C#
    Copy Code
    NPieSeries pie = (NPieSeries)(hitTestResult.Series);
    
    Visual Basic
    Copy Code
    Dim pie As NPieSeries = CType(hitTestResult.Series, NPieSeries)
    
    this ensures that we'll access the proper series in case the control displays multiple charts or multiple series in a chart. Finally it uses the DataPointIndex property to modify the detachment for the clicked pie.
    See Also