SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and now iOS Charting & Android Chart Components


I am using the 2D Heatmap with text as my working prototype. I wish to have a secondary Axis on the opposite side of my man Axis that displays a count for that row or column. To display this information is simple enough through using the LabelProvider (although two lines maybe a bit tricky), and I can do some stuff with the TickProvider when it gets a bit too busy.

My question is on how I can position these TickLabels to be in the center of a row/column?

My first thought was I could be cheeky and set the margin value to offset it in its style but it seems it only works so far with the TickLabel just displayed below the tick.

        <Style x:Key="LeftAxisLabelStyle" TargetType="s:NumericTickLabel">
                   <Setter Property="Margin" Value="0,0,0,-30"/>

enter image description here

What I am trying to achieve seems to be the default positioning for column charts, and histograms. I was wondering if there is a behind the scenes option or an override I’ve missed to set this?

Alternatively annotations maybe the way to go but I get the impression that this is more for on chart labels rather than for Axis?

p.s. I think when dealing with multiple Axes, you should give an warning/error if an “Id” is not given to secondary Axis as the graph will just show blank.

  • You must to post comments

Hi Matthew

I’ve been thinking about this as it is not an easy problem. Today the solution came to me! Use two axis, and modify the label placement on one!

Try this code:


<Window x:Class="WpfApplication17.MainWindow"
        Title="MainWindow" Height="350" Width="525">
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>

        <s:SciChartSurface x:Name="sciChart" Grid.Column="1" Padding="0" BorderThickness="0">

                <s:FastHeatMapRenderableSeries x:Name="heatmapSeries" Opacity="0.5" Maximum="200">
                            <GradientStop Offset="0" Color="DarkBlue"/>
                            <GradientStop Offset="0.2" Color="CornflowerBlue"/>
                            <GradientStop Offset="0.4" Color="DarkGreen"/>
                            <GradientStop Offset="0.6" Color="Chartreuse"/>
                            <GradientStop Offset="0.8" Color="Yellow"/>
                            <GradientStop Offset="1" Color="Red"/>

                <s:NumericAxis DrawMajorBands="True"/>

                <s:NumericAxis x:Name="primaryAxis" DrawMajorBands="True" DrawLabels="False"/>
                <local:NumericAxisEx Id="HiddenSecondaryAxis" 
                                     VisibleRange="{Binding ElementName=primaryAxis, Path=VisibleRange, Mode=TwoWay}"/>

                    <s:RolloverModifier ShowTooltipOn="Always" UseInterpolation="True" ReceiveHandledEvents="True"/>
                    <s:RubberBandXyZoomModifier ExecuteOn="MouseLeftButton"/>
                    <s:ZoomExtentsModifier ExecuteOn="MouseDoubleClick"/>


        <s:HeatmapColourMap Margin="10,10,60,40" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" Background="{Binding ElementName=sciChart, Path=Background}" Foreground="{Binding ElementName=sciChart, Path=Foreground}" ColorMap="{Binding ElementName=heatmapSeries, Path=ColorMap}" Minimum="{Binding ElementName=heatmapSeries, Path=Minimum}" Maximum="{Binding ElementName=heatmapSeries, Path=Maximum}" TextFormatting="0.00" Opacity="0.8" BorderBrush="#777" BorderThickness="1" Orientation="Vertical"/>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Numerics.CoordinateProviders;
using SciChart.Charting.Themes;
using SciChart.Charting.Visuals.Axes;

namespace WpfApplication17
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
        readonly Random _random = new Random();

        public MainWindow()

            heatmapSeries.DataSeries = CreateSeries(0);

        private IDataSeries CreateSeries(int index)
            double angle = Math.PI * 2 * index / 30;
            int w = 300, h = 200;
            var data = new double[h, w];
            for (int x = 0; x < w; x++)
            for (int y = 0; y < h; y++)
                var v = (1 + Math.Sin(x * 0.04 + angle)) * 50 + (1 + Math.Sin(y * 0.1 + angle)) * 50 * (1 + Math.Sin(angle * 2));
                var cx = 150; var cy = 100;
                var r = Math.Sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
                var exp = Math.Max(0, 1 - r * 0.008);
                data[y, x] = (v * exp + _random.NextDouble() * 50);

            return new Heatmap2DArrayDataSeries<int, int, double>(data, ix => ix, iy => iy);

    public class NumericAxisEx : NumericAxis
        protected override void DrawTickLabels(AxisCanvas canvas, TickCoordinates tickCoords, float offset)
            if (tickCoords.MajorTickCoordinates != null &&
                tickCoords.MajorTickCoordinates.Length > 2)
                offset += (tickCoords.MajorTickCoordinates[1] - tickCoords.MajorTickCoordinates[0]) * 0.5f;                

            base.DrawTickLabels(canvas, tickCoords, offset);


This results in the following output:

enter image description here

How it works

The secondary axis overrides AxisBase.DrawTickLabels. Here we compute an offset from the given coordinates, and modify that offset slightly. Then call the base for drawing.

We have two YAxis in the SciChartSurface. A primary axis used for all your series which draws Gridlines and ticks, and a secondary one which is invisible apart from labels.

You can further transform the numeric values to strings (if necessary) using the technique described here:

Best regards,

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.