Skip to main content Skip to footer

ComponentOne Chart Highlight Rectangle

ComponentOne Chart for WPF/ Silverlight provides selection support wherein we can select the datapoints and highlight them by changing the color of the selected points. But sometimes we want to drag the mouse through a selected area and highlight all the datapoints which lies inside the selected area. In this blog, we will discuss an approach to draw a rectangle on ComponentOne Chart using mouse move behaviour and then select and highlight multiple datapoints that lies between the rectangle selection. Here is a glimpse of the final sample in action:- We will start the implementation by adding a C1Chart control on your application's window which adds default fake data to the C1Chart control. This is how your XAML page will now look:-

  <c1chart:C1Chart Grid.Row="2"  ChartType="XYPlot"  Name="c1Chart1" >  
            <c1chart:C1Chart.Data>  
                <c1chart:ChartData>  
                    <c1chart:DataSeries Name="ds" Label="Series 2" RenderMode="Default" Values="20 22 19 24 25" PlotElementLoaded="ds_PlotElementLoaded"/>  
                    <c1chart:DataSeries Name ="ds1" Label="Series 3" RenderMode="Default" Values="8 12 10 12 17" PlotElementLoaded="ds_PlotElementLoaded"/>  
                    <c1chart:XYDataSeries Name="ds2" Label="Series 1" RenderMode="Default" Values="5,7,9,15,20" XValues="1,2,3,4,5" PlotElementLoaded="ds_PlotElementLoaded"></c1chart:XYDataSeries>  
                </c1chart:ChartData>  
            </c1chart:C1Chart.Data>  
            <c1chart:C1ChartLegend/>  
        </c1chart:C1Chart>

Once it is done, then we need to subscribe to MouseDown, MouseMove and MouseUp events of C1Chart and write the following code:-


void c1Chart1_MouseDown(object sender, MouseButtonEventArgs e)  
{  
    Point curPoint = e.GetPosition(c1Chart1.View);  
    rectSelectArea.Visibility = Visibility.Collapsed;  

    this.listBox1.Items.Clear();  
    foreach (Point point in this.plotElements.Keys)  
        this.plotElements[point].StrokeThickness = 1;  

    if (Keyboard.IsKeyDown(Key.LeftShift))  
    {  
        startPoint = curPoint;  
        point = c1Chart1.View.PointToData(startPoint);  
        obj.DataPoint = point;  
        rectSelectArea.Width = 0;  
        rectSelectArea.Height = 0;  
        rectSelectArea.Visibility = Visibility.Visible;  
    }  
    else  
    {  
        double distance = 0.0d;  
        for (int seriesIndex = 0; seriesIndex < c1Chart1.Data.Children.Count; seriesIndex++)  
        {  
            int pointIndex = c1Chart1.View.DataIndexFromPoint(curPoint, seriesIndex, MeasureOption.XY, out distance);  
            if (distance < 8)  
            {  
                foreach (Point point in this.plotElements.Keys)  
                {  
                    if (point.Y == seriesIndex && point.X == pointIndex)  
                    {  
                        this.plotElements[point].StrokeThickness = 7;  
                        this.listBox1.Items.Add(string.Format("Series={0}, Point={1}", seriesIndex, pointIndex));  
                    }  
                }  
            }  
        }  
    }  
}  

void c1Chart1_MouseMove(object sender, MouseEventArgs e)  
{  
    if (e.LeftButton != MouseButtonState.Pressed || rectSelectArea.Visibility != Visibility.Visible)  
        return;  

    var pos = e.GetPosition(c1Chart1.View);  
    rectSelectArea.Width = Math.Max(pos.X - startPoint.X, 0);  
    rectSelectArea.Height = Math.Max(pos.Y - startPoint.Y, 0);  

    Point endPoint = new Point(startPoint.X + rectSelectArea.Width, startPoint.Y + rectSelectArea.Height);  
    Point sPoint = c1Chart1.View.PointToData(startPoint);  
    Point ePoint = c1Chart1.View.PointToData(endPoint);  

    double left = Math.Min(sPoint.X, ePoint.X);  
    double right = Math.Max(sPoint.X, ePoint.X);  
    double top = Math.Max(sPoint.Y, ePoint.Y);  
    double bottom = Math.Min(sPoint.Y, ePoint.Y);  

    this.listBox1.Items.Clear();  

    foreach (Point point in this.plotElements.Keys)  
    {  
        double x = (double)this.plotElements[point].DataPoint.PointIndex;  
        double y = (double)this.plotElements[point].DataPoint.Value;  
        var pt = this.plotElements[point].DataPoint as XYDataSeries.XYDataPoint;  
        if (pt != null)  
        {  
            x = (double)pt.X;  
            y = (double)pt.Y;  
        }  

        if (left <= x && x <= right && bottom <= y && y <= top)  
        {  
            this.plotElements[point].StrokeThickness = 7;  
            this.listBox1.Items.Add(string.Format("Series={0}, Point={1}", point.Y, point.X));  
        }  
        else  
            this.plotElements[point].StrokeThickness = 1;  
    }  

    c1Chart1.EndUpdate();  
}  

void c1Chart1_MouseUp(object sender, MouseButtonEventArgs e)  
{  
    rectSelectArea.Visibility = Visibility.Collapsed;  
}  

So this completes the implementation process. Upon running the sample, if you drag the mouse while holding down the [SHIFT] key + left mouse button then a rectangle selection is drawn on the C1Chart control and the data contained in that selected area will be highlighted and its SeriesIndex and PointIndex is similarly extracted and displayed in listbox. To see it in action, you may download the sample with the complete implementation from the the below mentioned link. Download Sample

MESCIUS inc.

comments powered by Disqus