In this article:
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
- "Use DataLabel Provider" example (SciChart WPF Examples Suite → Style a Chart)
- Custom DataLabelProviders