Knowledgebase
Custom ChartModifiers - Part 2 - Custom ZoomPanModifier and Zooming on KeyPress
Posted by Andrew BT on 06 February 2019 11:54 AM

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!

Download the Custom ChartModifier Sandbox application

The complete application with all our custom chart modifiers can be downloaded in Part 1.

(3 vote(s))
Helpful
Not helpful

CONTACT US

Not sure where to start? Contact us, we are happy to help!


CONTACT US

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL. Email: Legal Company Number: 07430048, VAT Number: 101957725