SciChart WPF 2D Charts > 2D Chart Types > RenderableSeries APIs – DataPoint Labels
RenderableSeries APIs – DataPoint Labels

Introduction

Data labels are per-point text drawn by the Renderable Series itself. They are not WPF UIElement-based, so there are no per-label visual-tree elements, and labels scale to large datasets without the overhead of one WPF element per point.

Labels are generated by a DataLabelProvider attached to the series. Every series constructs a provider appropriate to its own geometry.

Data Point Labels have been introduced in SciChart WPF v9.1.

Adding Data Labels to a Chart

Setting ShowDataLabels="True" is all that is needed - the series' default provider does the rest.

Adding Data Labels to a Chart
Copy Code
<s:FastLineRenderableSeries Stroke="#68BCA0" StrokeThickness="2"
                            ShowDataLabels="True"
                            FontSize="14" Foreground="LimeGreen" />

Each series that supports data labels implements IDataLabelProviderSeries and creates its own default DataLabelProvider in its constructor:

  • FastLineRenderableSeries, XyScatterRenderableSeries, FastMountainRenderableSeries, FastCandlestickRenderableSeries, FastOhlcRenderableSeries - PointDataLabelProvider
  • FastBubbleRenderableSeries - PointDataLabelProvider, with LabelVerticalAnchorPoint set to Center so the label sits inside the bubble
  • FastColumnRenderableSeries, FastImpulseRenderableSeries - BarDataLabelProvider
  • FastBandRenderableSeries - BandDataLabelProvider
  • FastBoxPlotRenderableSeries - BoxPlotDataLabelProvider
  • FastErrorBarsRenderableSeries - ErrorBarDataLabelProvider
  • StackedColumnRenderableSeries, StackedMountainRenderableSeries, StackedBoxPlotRenderableSeries - their respective StackedColumnDataLabelProvider, StackedMountainDataLabelProvider, StackedBoxPlotDataLabelProvider

Heatmap series do not implement IDataLabelProviderSeries - they use their own, separate label rendering mechanisms.

The code-behind equivalent of the XAML above is:

Adding Data Labels to a Chart
Copy Code
lineSeries.ShowDataLabels = true;

Styling Label Appearance

Labels take their font and color from the series' own WPF Control properties - the same properties used to style everything else on the series:

  • FontSize - defaults to 12 via the series' default style
  • FontFamily - not set explicitly by the default style; resolves through the inherited Control default (typically Segoe UI on Windows)
  • FontWeight - Normal
  • FontStyle - Normal
  • Foreground - the label text color; defaults to the theme's tick text brush, a light color on the built-in dark themes (StackedColumnRenderableSeries defaults it to White instead, for backward compatibility with its legacy LabelColor property)
Styling Label Appearance
Copy Code
<s:FastLineRenderableSeries ShowDataLabels="True"
                            FontSize="14" FontWeight="SemiBold" Foreground="Cyan" />

Formatting Label Text

Numeric formatting

LabelTextFormatting (default "0.##") is a standard .NET numeric format string applied to the Y value.

Numeric formatting
Copy Code
lineSeries.DataLabelProvider = new PointDataLabelProvider
{
    LabelTextFormatting = "0.00"
};

Text from metadata

MetadataLabelSelector (Func<IPointMetadata, string>) supplies custom text from point metadata; when set, it takes priority over numeric formatting.

Text from metadata
Copy Code
public class LabelPointMetadata : IPointMetadata
{
    public event PropertyChangedEventHandler PropertyChanged;
    public LabelPointMetadata(string label) { Label = label; }
    public bool IsSelected { get; set; }
    public string Label { get; }
}
dataSeries.Append(x, y, new LabelPointMetadata("Sample A"));
lineSeries.DataLabelProvider = new PointDataLabelProvider
{
    MetadataLabelSelector = md => (md as LabelPointMetadata)?.Label,
    LabelVerticalAnchorPoint = VerticalAnchorPoint.Auto,
    SkipMode = DataLabelSkipMode.SkipIfOverlap
};

If the selector returns null for a point, the label falls back to the formatted Y value; returning an empty string suppresses the label for that point entirely.

After mutating metadata that the selector reads, call provider.InvalidateLabels() to force regeneration - data and viewport changes are detected automatically, but a metadata mutation is not.

Positioning Labels

  • LabelHorizontalAnchorPoint (Left / Center / Right, default Center) - which horizontal edge of the label is pinned to the point
  • LabelVerticalAnchorPoint (Top / Center / Bottom / Auto, default Auto) - Auto is data-aware: the label sits above the point and flips below at local minima (valleys), and respects flipped or vertical axes
  • LabelPadding (Thickness, default 0,3,0,3) - the offset from the anchor point, and also the minimum gap used for overlap detection
Positioning Labels
Copy Code
<s:FastLineRenderableSeries ShowDataLabels="True" FontSize="14" Foreground="Cyan">
    <s:FastLineRenderableSeries.DataLabelProvider>
        <dataLabelProviders:PointDataLabelProvider LabelVerticalAnchorPoint="Top" />
    </s:FastLineRenderableSeries.DataLabelProvider>
</s:FastLineRenderableSeries>

Managing Label Density

SkipMode

SkipMode (DataLabelSkipMode, default SkipIfOverlap) controls how overlapping or repeated labels are thinned:

  • ShowAll - draw every label regardless of overlap
  • SkipIfOverlap (default) - hide overlapping labels using a stable two-pass algorithm, so labels do not flicker in and out while panning
  • SkipIfSame - hide a label if its text is the same as the previous visible label
Using SkipMode
Copy Code
lineSeries.DataLabelProvider = new PointDataLabelProvider
{
    SkipMode = DataLabelSkipMode.SkipIfSame
};

SkipNumber

SkipNumber (int, default 0) draws every (N + 1)-th label. It is keyed to the absolute data-series index, so the same labels stay visible as the viewport moves.

Using SkipNumber
Copy Code
lineSeries.DataLabelProvider = new PointDataLabelProvider
{
    SkipNumber = 4 // draw every 5th label
};

PointCountThreshold

PointCountThreshold (int, default 1000) hides all labels automatically once the series has more visible points than this. Raise it deliberately when labelling only a small, curated subset of a large series.

Using PointCountThreshold
Copy Code
lineSeries.DataLabelProvider = new PointDataLabelProvider
{
    PointCountThreshold = 5000
};

Series-Specific Providers

Columns and Impulse

BarDataLabelProvider adds BarAnchorPoint, which controls where on the bar geometry the label attaches: Auto (default) places it at the value tip, outside the bar; Top, Bottom and Center place it at the corresponding geometric edge of the bar.

DataLabelProviders for Columns and Impulse Series
Copy Code
<s:FastColumnRenderableSeries ShowDataLabels="True">
    <s:FastColumnRenderableSeries.DataLabelProvider>
        <dataLabelProviders:BarDataLabelProvider BarAnchorPoint="Center" />
    </s:FastColumnRenderableSeries.DataLabelProvider>
</s:FastColumnRenderableSeries>

Band

BandDataLabelProvider adds LabelSource (BandLabelSource: Y, Y1, Both; default Both), which selects which of the band's two Y channels receives labels.

DataLabelProviders for Band Series
Copy Code
<s:FastBandRenderableSeries ShowDataLabels="True">
    <s:FastBandRenderableSeries.DataLabelProvider>
        <dataLabelProviders:BandDataLabelProvider LabelSource="Y1" />
    </s:FastBandRenderableSeries.DataLabelProvider>
</s:FastBandRenderableSeries>

Box Plot and Error Bars

BoxPlotDataLabelProvider and ErrorBarDataLabelProvider inherit BarAnchorPoint from BarDataLabelProvider; Top and Bottom anchor the label to the whisker (box plot) or error (error bars) extremes rather than the Y value.

DataLabelProviders for Box Plot and Error Bar Series
Copy Code
<s:FastBoxPlotRenderableSeries ShowDataLabels="True">
    <s:FastBoxPlotRenderableSeries.DataLabelProvider>
        <dataLabelProviders:BoxPlotDataLabelProvider BarAnchorPoint="Top" />
    </s:FastBoxPlotRenderableSeries.DataLabelProvider>
</s:FastBoxPlotRenderableSeries>

Stacked series

StackedColumnDataLabelProvider, StackedMountainDataLabelProvider and StackedBoxPlotDataLabelProvider position labels at the accumulated (stacked) segment position rather than the raw Y value. StackedColumnDataLabelProvider additionally exposes HideIfExceedsBounds (default true), which hides a label that is larger than its segment; in 100%-stacked mode values are shown as percentages automatically, and its LabelTextFormatting defaults to "0.00".

DataLabelProviders for Stacked Series
Copy Code
<s:StackedColumnRenderableSeries ShowDataLabels="True">
    <s:StackedColumnRenderableSeries.DataLabelProvider>
        <dataLabelProviders:StackedColumnDataLabelProvider HideIfExceedsBounds="False" />
    </s:StackedColumnRenderableSeries.DataLabelProvider>
</s:StackedColumnRenderableSeries>

MVVM Support

Series ViewModels that support data labels derive from LabelCapableRenderableSeriesViewModel, which exposes ShowDataLabels (default false), DataLabelProvider (seeded from a series-appropriate default), and the appearance properties Foreground, FontSize (default 12), FontFamily, FontWeight and FontStyle.

Applying DataLabelProvider in MVVM
Copy Code
var lineVm = new LineRenderableSeriesViewModel
{
    DataSeries = dataSeries,
    Stroke = Colors.LimeGreen,
    ShowDataLabels = true,
    FontSize = 14,
    Foreground = Brushes.LimeGreen,
    DataLabelProvider = new PointDataLabelProvider
    {
        LabelVerticalAnchorPoint = VerticalAnchorPoint.Top,
        SkipMode = DataLabelSkipMode.SkipIfOverlap
    }
};
chart.RenderableSeries.Add(lineVm);

Tips and Best Practices

  • Density first: prefer SkipIfOverlap (the default) over ShowAll on dense data; use SkipNumber for deterministic thinning when you want a predictable, fixed subset of labels.
  • Large series: PointCountThreshold suppresses all labels above 1000 points - raise it consciously when labelling a curated subset, for example by combining it with a MetadataLabelSelector that returns "" for the points you don't want labelled.
  • One provider per series: a provider is stateful and single-series - never share one instance between two series or two surfaces.
  • Metadata changes: call InvalidateLabels() after mutating metadata that your MetadataLabelSelector reads; the provider cannot detect that change on its own.
  • Vertical anchor choice: Auto is the right default for line-like data; use Center for bubbles (the bubble series already defaults to it, in both the view layer and MVVM).

See Also