Custom ChartModifiers - Part 2 - Custom ZoomPanModifier and Zooming on KeyPress

Created by Lex Smith, Modified on Fri, 29 Mar 2024 at 02:04 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 2 - Creating a Custom ZoomPanModifier


We created a video on YouTube showing how to create your very own custom ZoomPanModifier using the ChartModifier API! Also, we show you how to zoom in and out on Keypress, e.g. CTRL+, CTRL-. In this video we demonstrate from start to end how to create your own zooming and panning modifiers in under 150 lines of code.



The SimpleZoomPanModifier Source


The entire SimpleZoomPanModifier class is included below. The code is fairly self-explanatory. We inherit ChartModifierBase, override OnModifierMouseMove() and Scroll the X and Y Axis by the change in mouse-pixels since the last MouseMove event.


using System.Windows;
using SciChart.Charting;
using SciChart.Charting.ChartModifiers;
using SciChart.Core.Utility.Mouse;
 
namespace TestSuite.ExampleSandbox.CustomModifiers
{
    /// 
    /// A single X-Y axis implementation of a ZoomPanModifier, used to demonstrate the ChartModifierBase and Axis Interactivity APIs in SciChart
    /// 
    public class SimpleZoomPanModifier : ChartModifierBase
    {
        private Point? _lastPoint;
 
        public override void OnModifierMouseDown(ModifierMouseArgs e)
        {
            base.OnModifierMouseDown(e);
 
            e.Handled = true;
            _lastPoint = e.MousePoint;
        }
 
        public override void OnModifierMouseMove(ModifierMouseArgs e)
        {
            base.OnModifierMouseMove(e);
            if (_lastPoint == null) return;
 
            var currentPoint = e.MousePoint;
            var xDelta = currentPoint.X - _lastPoint.Value.X;
            var yDelta = _lastPoint.Value.Y - currentPoint.Y;
 
            using (ParentSurface.SuspendUpdates())
            {
                // Scroll the XAxis by the number of pixels since the last update
                XAxis.Scroll(XAxis.IsHorizontalAxis ? xDelta : -yDelta, ClipMode.None);
 
                // Scroll the YAxis by the number of pixels since the last update
                YAxis.Scroll(YAxis.IsHorizontalAxis ? -xDelta : yDelta, ClipMode.None);
 
                // Note.. can be extended for multiple YAxis XAxis, just iterate over all axes on the parent surface
            }
 
            _lastPoint = currentPoint;
        }
 
        public override void OnModifierMouseUp(ModifierMouseArgs e)
        {
            base.OnModifierMouseUp(e);
            _lastPoint = null;
        }
    }
}


So, What Else could you do?


Quite a lot actually! If you check out our article on Axis Interactivity APIs you can see the true power of combining Axis Interactivity with ChartModifiers ...


Combine the ChartModifier API with Axis Interactivity APIs and you can achieve virtually any combination of zooming and panning with SciChart!


Zooming In / Out on Key Presses


Another custom modifier we demonstrate in the video above is the SimpleZoomInOutModifier. This zooms the chart in/out by a single step when the user presses CTRL+ and CTRL-.


using System;
using System.Windows;
using System.Windows.Input;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Visuals;
 
namespace TestSuite.ExampleSandbox.CustomModifiers
{
    /// 
    /// A single X-Y axis implementation of a Zooming In / Out on KeyDown (CTRL+, CTRL-), used to demonstrate the ChartModifierBase and Axis Interactivity APIs in SciChart
    /// 
    public class SimpleZoomInOutModifier : ChartModifierBase
    {
        public static readonly DependencyProperty ZoomFractionProperty = DependencyProperty.Register("ZoomFraction", typeof(double), typeof(SimpleZoomInOutModifier), new PropertyMetadata(0.1));
 
        public double ZoomFraction
        {
            get { return (double)GetValue(ZoomFractionProperty); }
            set { SetValue(ZoomFractionProperty, value); }
        }
 
        void SciChart_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            double factor = 0;
 
            if (e.Key == Key.Add && (Keyboard.Modifiers & ModifierKeys.Control) > 0)
            {
                // On CTRL+, Zoom In
                factor = -ZoomFraction;
            }
            if (e.Key == Key.Subtract && (Keyboard.Modifiers & ModifierKeys.Control) > 0)
            {
                // On CTRL-, Zoom Out
                factor = ZoomFraction;
            }
 
            using (ParentSurface.SuspendUpdates())
            {
                // Zoom the XAxis by the required factor
                XAxis.ZoomBy(factor, factor, TimeSpan.FromMilliseconds(500));
 
                // Zoom the YAxis by the required factor
                YAxis.ZoomBy(factor, factor, TimeSpan.FromMilliseconds(500));
 
                // Note.. can be extended for multiple YAxis XAxis, just iterate over all axes on the parent surface
            }
        }
 
        public override void OnAttached()
        {
            base.OnAttached();
            var scichart = ((SciChartSurface)ParentSurface);
 
            var mainWindow = FindLogicalParent<Window>(scichart);
 
            mainWindow.PreviewKeyDown -= SciChart_PreviewKeyDown;
            mainWindow.PreviewKeyDown += SciChart_PreviewKeyDown;
        }
 
        private T FindLogicalParent<T>(SciChartSurface scichart) where T : class
        {
            var parent = (FrameworkElement)scichart.Parent;
            while (parent != null)
            {
                var candidate = parent as T;
                if (candidate != null) return candidate;
 
                parent = (FrameworkElement)parent.Parent;
            }
 
            return null;
        }
    }
}


The code should be fairly self-explanatory. We subscribe to KeyDown on the parent Window of the SciChartSurface, and zoom in/out by a simple zoom factor depending on what key was pressed. That's it!


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 atleast one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article