Custom ChartModifiers - Part 3 - Custom Select and Drag a Series

Created by Lex Smith, Modified on Fri, 29 Mar at 12:53 AM by Lex Smith

The ChartModifier API


If you haven't read it already, please see our article on Custom Chartmodifier API Overview. In this article, we introduce the basics of the ChartModifier API including an overview of this powerful base class.


The ChartModifier API is by far the most powerful API in the SciChart library. Using this API you can create behaviours which you can attach to a chart to perform custom Zooming, Panning, Annotation & Markers, Legend output and much much more. Any time you want to do something in C# code to alter the behaviour of a SciChartSurface you should be thinking about creating a custom modifier to do it.


Custom ChartModifiers Part 3 - Creating a Custom ZoomPanModifier


A lot of people ask us how you can click to select and drag a Series on a SciChartSurface. We tell them "you'll have to create a custom ChartModifier!". In this next video, we show you how to create your very own custom Series-Drag modifier using the ChartModifier API! What's more impressive, is this powerful feature can be achieved in just 70 lines of code.



The SimpleSeriesDragModifier Source


The entire SimpleSeriesDragModifier class is included below. The code is fairly self-explanatory. Instead of inheriting ChartModifierBase, we inherit SeriesSelectionModifier, as this base-class handles the selection part very well.


Next, with a selected series on Mouse Move, we simply offset the series vertically.


using System;
using System.Linq;
using System.Windows;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Visuals.RenderableSeries;
using SciChart.Core.Utility.Mouse;
 
namespace TestSuite.ExampleSandbox.CustomModifiers
{
    public class SimpleSeriesDragModifier : SeriesSelectionModifier
    {
        private IRenderableSeries _selectedSeries;
        private Point _lastMousePoint;
 
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            // Deliberately call OnModifierMouseUp in MouseDown handler to perform selection
            base.OnModifierMouseUp(e);
 
            var selectedSeries = this.ParentSurface.RenderableSeries.FirstOrDefault(x => x.IsSelected);
 
            if (selectedSeries == null)
                return;
 
            _selectedSeries = selectedSeries;
            _lastMousePoint = e.MousePoint;
        }
 
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);
 
            if (_selectedSeries == null) return;
 
            var dataSeries = _selectedSeries.DataSeries as XyDataSeries<DateTime, double>;
            if (dataSeries == null)
            {
                throw new InvalidOperationException("This modifier is only configured to work with XyDataSeries<double,double>");
            }
 
            var currentMousePoint = e.MousePoint;
            double currentYValue = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(currentMousePoint.Y);
            double startYValue = _selectedSeries.YAxis.GetCurrentCoordinateCalculator().GetDataValue(_lastMousePoint.Y);
 
            var deltaY = currentYValue - startYValue;
 
            OffsetSeries(dataSeries, deltaY);
 
            _lastMousePoint = currentMousePoint;
        }
 
        public void OffsetSeries(XyDataSeries<DateTime, double> series, double offset)
        {
            var originalXData = series.XValues.ToArray();
            var originalYData = series.YValues.ToArray();
 
            // To Offset the series, clear and recreate data
            using (series.SuspendUpdates())
            {
                series.Clear();
                series.Append(originalXData, originalYData.Select(y => y + offset));
            }
        }
 
        public override void OnModifierMouseUp(ModifierMouseArgs e)
        {
            _selectedSeries = null;
            base.OnModifierMouseUp(e);
        }
    }
}


Get the Custom ChartModifier Sandbox application


The link to the complete application with all our custom chart modifiers can be found in Part 1.



Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article