Full Control over Axis Ticks
In the previous article we showed you how to change the Axis.AutoTicks, Axis.MajorDelta and Axis.MinorDelta properties to change the axis tick (label and gridline) interval. This is fine for static charts, but for dynamic charts where you need full customisation over the axis tick output, you need to use the Axis.TickProvider API.
Overriding the Axis.DeltaCalculator
To have full control over the calculator for MajorDelta and MinorDelta you will need to create a custom DeltaCalculator.
First, create a class that implements IDeltaCalculator for numeric axes or IDateDeltaCalculator for time axes. The IDeltaCalculator.GetDeltaFromRange method should be implemented to get min and max of visible range and amount of minor ticks for each major and amount of major ticks. So here, you can place the logic of delta values calculation.
Overriding the Axis.DeltaCalculator |
Copy Code |
---|---|
/// <summary> /// Provides an interface for Delta calculators /// </summary> public interface IDeltaCalculator { /// <summary> /// Given an absolute Axis Min and Max, returns a TickRange instance /// containing sensible MinorDelta and MajorDelta values /// </summary> IAxisDelta GetDeltaFromRange(IComparable min, IComparable max, int minorsPerMajor, uint maxTicks); } /// <summary> /// Defines the interface for DateTime or TimeSpan Delta calculators /// </summary> public interface IDateDeltaCalculator : IDeltaCalculator { /// <summary> /// Given an absolute Axis Min and Max, returns a TickRange instance /// containing sensible MinorDelta and MajorDelta values /// </summary> new TimeSpanDelta GetDeltaFromRange(IComparable min, IComparable max, int minorsPerMajor, uint maxTicks); } |
Next, you will need to set your DeltaCalculator instance on the AxisBase.DeltaCalculator property.
Example – Creating a custom DeltaCalculator for a NumericAxis
For an example of creating a DeltaCalculator for a NumericAxis, see below:
Creating a custom DeltaCalculator for a NumericAxis |
Copy Code |
---|---|
public class CustomNumericDeltaCalculator : IDeltaCalculator { private const uint DefaultTicksCount = 10; /// <summary> /// Given an absolute Axis Min and Max, returns a TickRange instance containing sensible MinorDelta and MajorDelta values /// </summary> public IAxisDelta<double> GetDeltaFromRange(double min, double max, int minorsPerMajor, uint maxTicks = DefaultTicksCount) { // Given the min = Axis.VisibleRange.Min, // the max = Axis.VisibleRange.Max // minorsPerMajor = requested minor ticks per major ticks // maxTicks = requested maximum number of major ticks // // Note: Your delta calculation here to calculate minorDelta, majorDelta double deltaMin, deltaMax; // Return an AxisDelta return new DoubleAxisDelta(deltaMin, deltaMax); } IAxisDelta IDeltaCalculator.GetDeltaFromRange(IComparable min, IComparable max, int minorsPerMajor, uint maxTicks) { return GetDeltaFromRange(min.ToDouble(), max.ToDouble(), minorsPerMajor, maxTicks); } } |
Custom DeltaCalculator Usage (Code)
Custom DeltaCalculator Usage |
Copy Code |
---|---|
public class NumericAxisEx : NumericAxis { private IDeltaCalculator _customDeltaCalculator = new CustomNumericDeltaCalculator(); protected override IDeltaCalculator GetDeltaCalculator() { return _customDeltaCalculator; } } |
Custom DeltaCalculator Usage (XAML)
Custom DeltaCalculator Usage |
Copy Code |
---|---|
<!-- where xmlns:s="http://schemas.abtsoftware.co.uk/scichart" --> <!-- Assumes you have declared your custom NumericAxisEx in code --> <s:SciChartSurface> <s:SciChartSurface.XAxis> <yourNamespace:NumericAxisEx/> </s:SciChartSurface.XAxis> <!-- YAxis, RenderableSeries omitted for brevity --> </s:SciChartSurface> |
Example – Creating a custom DeltaCalculator for a DateTime or TimeSpanAxis
Creating a custom DeltaCalculator for a DateTime or TimeSpanAxis |
Copy Code |
---|---|
public class CustomDateTimeDeltaCalculator : IDateDeltaCalculator { IAxisDelta IDeltaCalculator.GetDeltaFromRange(IComparable min, IComparable max, int minorsPerMajor, uint maxTicks) { return GetDeltaFromRange(min.ToDouble(), max.ToDouble(), minorsPerMajor, maxTicks); } public TimeSpanDelta GetDeltaFromRange(IComparable min, IComparable max, int minorsPerMajor, uint maxTicks) { // Given the min = Axis.VisibleRange.Min, // the max = Axis.VisibleRange.Max // minorsPerMajor = requested minor ticks per major ticks // maxTicks = requested maximum number of major ticks // // NOTE: Your delta calculation here to calculate minorDelta, majorDelta TimeSpan deltaMin, deltaMax; // Return an AxisDelta return new TimeSpanDelta(deltaMin, deltaMax); } } |
Custom DeltaCalculator Usage (Code)
Custom DeltaCalculator Usage |
Copy Code |
---|---|
public class DateTimeAxisEx : DateTimeAxis { private IDeltaCalculator _customDeltaCalculator = new CustomDateTimeDeltaCalculator(); protected override IDeltaCalculator GetDeltaCalculator() { return _customDeltaCalculator; } } |
Custom DeltaCalculator Usage (XAML)
Custom DeltaCalculator Usage |
Copy Code |
---|---|
<!-- where xmlns:s="http://schemas.abtsoftware.co.uk/scichart" --> <!-- Assumes you have declared your custom DateTimeAxisEx in code --> <s:SciChartSurface> <s:SciChartSurface.XAxis> <yourNamespace:DateTimeAxisEx/> </s:SciChartSurface.XAxis> <!-- YAxis, RenderableSeries omitted for brevity --> </s:SciChartSurface> |
Overidding the Axis.TickProvider
By default each Axis type has it’s own TickProvider type, e.g.
Axis Type | TickProvider Type |
NumericAxis | NumericTickProvider |
DateTimeAxis | DateTimeTickProvider |
TimeSpanAxis | TimeSpanTickProvider |
CategoryDateTimeAxis | NumericTickProvider |
LogarithmicNumericAxis | LogarithmicNumericTickProvider |
PolarXAxis | NumericTickProvider |
PolarYAxis | NumericTickProvider |
You can create your own, or inherit one of our TickProvider types to completely control the generation of axis ticks (label and gridline intervals).
The easiest way to create new tick provider is to use TickProvider base class where T is the axis data-type, e.g. DateTime for DateTimeAxis, double for NumericAxis etc.
Next, you need to implement two abstract methods for the generation of major and minor ticks. In these methods you need to place the logic of tick generation and return arrays with data-values where ticks (gridlines, labels) should be displayed.
Example – Creating a NumericAxis TickProvider
For a demonstration of using the TickProvider API we are going to create TickProvider for the NumericAxis type by inherting NumericTickProvider. This tick provider should divide the axis into 5 equal parts, using major tick gridlines and without minor ticks.
Creating a NumericAxis TickProvider |
Copy Code |
---|---|
public class CustomTickProvider : NumericTickProvider { private const int MajorTickCount = 5; public override double[] GetMajorTicks(IAxisParams axis) { var visibleRange = (DoubleRange) axis.VisibleRange; var ticks = new double[MajorTickCount + 1]; var step = visibleRange.Diff / MajorTickCount; var min = visibleRange.Min; for (int i = 0; i < MajorTickCount + 1; i++) { ticks[i] = min + step * i; } return ticks; } public override double[] GetMinorTicks(IAxisParams axis) { return new double[0]; } } |
Usage (XAML)
Usage |
Copy Code |
---|---|
<!-- where xmlns:s="http://schemas.abtsoftware.co.uk/scichart" --> <s:SciChartSurface> <s:SciChartSurface.Resources> <local:CustomTickProvider x:Key="CustomTickProvider "/> </s:SciChartSurface.Resources> <s:SciChartSurface.XAxis> <s:NumericAxis DeltaCalculator="{StaticResource CustomTickProvider "/> </s:SciChartSurface.XAxis> <!-- YAxis, RenderableSeries omitted for brevity --> </s:SciChartSurface> |
Usage (Code)
Usage |
Copy Code |
---|---|
var axis = new NumericAxis(); axis.TickProvider = new CustomTickProvider(); |
Result
The Custom Tickprovider divides the axis into five sections, and removes minor gridlines
Note: Obviously there’s a lot more you coul do with this API, for instance, if you want to dynamically control the tick frequency as you zoom, this would be the place to do it!
Creating a custom TickProvider for a TimeSpanAxis or DateTimeAxis
The process for creating a TickProvider for a TimeSpanAxis or DateTimeAxis is similar, except you need to change the base class and return TimeSpan, or DateTime arrays.
Custom TickProvider for a TimeSpanAxis
Custom TickProvider for a TimeSpanAxis |
Copy Code |
---|---|
// 1. Create a class which inherits TimeSpanTickProvider // 2. Return an array of IComparable, but actual elements must be TimeSpans // 3. Assign to the TimeSpanAxis.TickProvider property public class CustomTimeSpanTickProvider : TimeSpanTickProvider { public override IComparable[] GetMajorTicks(IAxisParams axis) { // TODO: calculate ticks return new IComparable[] { new TimeSpan(2015, 01, 01), new TimeSpan(2015, 01, 02), new TimeSpan(2015, 01, 03), // ... }; } public override IComparable[] GetMinorTicks(IAxisParams axis) { // TODO: calculate ticks return new IComparable[] { new TimeSpan(2015, 01, 01), new TimeSpan(2015, 01, 02), new TimeSpan(2015, 01, 03), // ... }; } } |
Custom TickProvider for a DateTimeAxis
Custom TickProvider for a DateTimeAxis |
Copy Code |
---|---|
// 1. Create a class which inherits DateTimeTickProvider // 2. Return an array of IComparable, but actual elements must be DateTimes // 3. Assign to the DateTimeAxis.TickProvider property public class CustomDateTimeTickProvider : DateTimeTickProvider { public override IComparable[] GetMajorTicks(IAxisParams axis) { // TODO: calculate ticks return new IComparable[] { new DateTime(2015, 01, 01), new DateTime(2015, 01, 02), new DateTime(2015, 01, 03), // ... }; } public override IComparable[] GetMinorTicks(IAxisParams axis) { // TODO: calculate ticks return new IComparable[] { new DateTime(2015, 01, 01), new DateTime(2015, 01, 02), new DateTime(2015, 01, 03), // ... }; } } |