This is a migrated thread and some comments may be shown as answers.

Lasso selection of data points?

3 Answers 200 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Louis
Top achievements
Rank 1
Louis asked on 30 Jan 2014, 08:26 PM
I need to allow users to select multiple points on a ChartView chart by click-and-dragging the mouse, ideally in an arbitrary closed shape (lasso), but minimally in the rectangle formed by the positions of the mouse-down and mouse-up events. Handling the mouse events to define the area, and performing a hit-test on the points should be easy enough for the rectangular case, but I also need visual feedback on the screen showing the shape being drawn.

Are there any examples available showing the best way to accomplish something this with a ChartView? If not, is there anything besides the mouse events I should be exploring, and what's the best approach for the visual feedback aspect?

Thanks,
Louis

3 Answers, 1 is accepted

Sort by
0
Accepted
Petar Marchev
Telerik team
answered on 03 Feb 2014, 02:45 PM
Hi Louis,

What you describe sounds like a drag-to-select feature. Currently we do not have this built-in and you will need to handle this manually.

I have attached a demo project for this. In it, you will find that the mouse down, up and move events are used. A selection rectangle is shown to annotate the selection range and the IsSelected property of the data points is handled in accordance to this selection range. Hope you will find it useful. 

Regards,
Petar Marchev
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Louis
Top achievements
Rank 1
answered on 03 Feb 2014, 04:13 PM
This is excellent, thank you very much Petar!

Louis
0
Louis
Top achievements
Rank 1
answered on 10 Mar 2014, 09:34 PM
For anyone finding this post later, I had to make some changes to the ChartUtilities to allow for panning and zooming correctly. I've included the relevant bits below for reference, as apparently I can't attach the cs files.

Also, in my case, I wasn't able to use LayoutSlot.Center.X/Y in UpdateDataPointsInSelectionRectangle, as my points had large heights and widths for some reason. I had to change to just using LayoutSlot.X/Y.

Louis

private static void chart_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    RadCartesianChart chart = (RadCartesianChart)sender;
    Point fromPosition = e.GetPosition(chart);
    SetFromPosition(chart, fromPosition);
    SetToPosition(chart, fromPosition);
 
    Point plotPoint = ConvertWindowToPlotAreaClip(fromPosition, chart);
 
    if (!chart.PlotAreaClip.Contains(plotPoint.X, plotPoint.Y))
    {
        return;
    }
 
    chart.CaptureMouse();
 
    Canvas adorner = Telerik.Windows.Controls.ChildrenOfTypeExtensions.ChildrenOfType<Canvas>(chart).First(c => c.Name == "adornerContainer");
    Style style = GetSelectionRectangleStyle(chart);
    FrameworkElement selectionRectangle = BuildSelectionRectangle(style);
    adorner.Children.Add(selectionRectangle);
    UpdateSelectionRectanglePositionAndSize(chart);
    SetIsSelectionRectangleShown(chart, true);
}
 
private static void chart_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    RadCartesianChart chart = (RadCartesianChart)sender;
    chart.ReleaseMouseCapture();
 
    Canvas adorner = Telerik.Windows.Controls.ChildrenOfTypeExtensions.ChildrenOfType<Canvas>(chart).First(c => c.Name == "adornerContainer");
    FrameworkElement selectionRectangle = Telerik.Windows.Controls.ChildrenOfTypeExtensions.ChildrenOfType<FrameworkElement>(chart).FirstOrDefault(r => object.Equals(r.Tag, SelectionRectangleTag));
    if (selectionRectangle != null)
    {
        adorner.Children.Remove(selectionRectangle);
    }
    SetIsSelectionRectangleShown(chart, false);
}
 
private static void chart_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
    RadCartesianChart chart = (RadCartesianChart)sender;
    if (!GetIsSelectionRectangleShown(chart))
    {
        return;
    }
 
    var plotAreaClip = chart.PlotAreaClip;
 
    Point windowsPoint = ConvertPlotAreaClipToWindow(new Point(plotAreaClip.X,plotAreaClip.Y), chart);
 
    double maxX = windowsPoint.X + plotAreaClip.Width;
    double maxY = windowsPoint.Y + plotAreaClip.Height;
 
    Point toPosition = e.GetPosition(chart);
    toPosition.X = Math.Max(windowsPoint.X, toPosition.X);
    toPosition.X = Math.Min(toPosition.X, maxX);
    toPosition.Y = Math.Max(windowsPoint.Y, toPosition.Y);
    toPosition.Y = Math.Min(toPosition.Y, maxY);
    SetToPosition(chart, toPosition);
 
    UpdateSelectionRectanglePositionAndSize(chart);
    UpdateDataPointsInSelectionRectangle(chart);
}
 
private static void UpdateDataPointsInSelectionRectangle(RadCartesianChart chart)
{
    Point fromPosition = ConvertWindowToPlotAreaClip(GetFromPosition(chart),chart);
    Point toPosition = ConvertWindowToPlotAreaClip(GetToPosition(chart), chart);
    Rect rect = new Rect(fromPosition, toPosition);
 
    foreach (CategoricalSeries series in chart.Series)
    {
        foreach (CategoricalDataPoint dp in series.DataPoints)
        {
            dp.IsSelected = rect.Contains(dp.LayoutSlot.Center.X, dp.LayoutSlot.Center.Y);
        }
    }
}
 
 
private static Point ConvertWindowToPlotAreaClip(Point from, RadCartesianChart chart)
{
    return new Point()
    {
        X = from.X + chart.HorizontalZoomRangeStart * chart.PlotAreaClip.Width * chart.Zoom.Width,
        Y = from.Y + (1.0 - chart.VerticalZoomRangeEnd) * chart.PlotAreaClip.Height * chart.Zoom.Height
    };
}
 
private static Point ConvertPlotAreaClipToWindow(Point from, RadCartesianChart chart)
{
    return new Point()
    {
        X = from.X - chart.HorizontalZoomRangeStart * chart.PlotAreaClip.Width * chart.Zoom.Width,
        Y = from.Y - (1.0 - chart.VerticalZoomRangeEnd) * chart.PlotAreaClip.Height * chart.Zoom.Height
    };
}
Tags
ChartView
Asked by
Louis
Top achievements
Rank 1
Answers by
Petar Marchev
Telerik team
Louis
Top achievements
Rank 1
Share this question
or