In this article:
Introduction
The DataPoint Labels feature supports two levels of customization. The first is to subclass PointDataLabelProvider and override one hook method, keeping the built-in measure, position and skip pipeline. The second is to implement IDataLabelProvider directly, for full control over every label via the direct-draw path.
Data Point Labels have been introduced in SciChart WPF v9.1.
How Label Rendering Works
A DataLabelProvider generates raw labels, defined by the DataLabel structure with Text, AnchorPoint and Color, for the current render pass. The series' drawing pipeline then measures the text, computes the final position, applies skip/overlap logic, and draws.
The DataLabel struct carries these fields:
- Key - a stable identity for the label, used for inner caching in the default implementation
- Text - the label text
- AnchorPoint - the pixel coordinate of the data point anchor
- Position - the final top-left draw position, after alignment and offset
- Size - the measured size of the text
- Color - the label's foreground color
- IsVisible - whether the label is drawn
When the provider derives from PointDataLabelProvider, only Key Text, AnchorPoint and Color need to be filled in during generation. The drawing pipeline then fills in Size, Position and IsVisible.
| Creating Labels |
Copy Code |
|---|---|
protected virtual string GetLabelText(int index, double yValue) { /* ... */ } public virtual Color GetLabelColor(int index, double yValue) { /* ... */ } public virtual Point GetLabelPosition(int index, Point anchorPoint, Size textSize, IRenderPassData renderPassData) { /* ... */ } | |
Customizing Label Text
Override GetLabelText to change how label text is derived.
Return null or an empty string to skip the label for that point entirely - this is the mechanism for selective labelling.
| Customizing Label Text |
Copy Code |
|---|---|
public class ThresholdDataLabelProvider : PointDataLabelProvider { public double Threshold { get; set; } protected override string GetLabelText(int index, double yValue) { // Returning null skips the label for this point return yValue >= Threshold ? base.GetLabelText(index, yValue) : null; } } | |
Customizing Label Color
Override GetLabelColor to color labels based on data. The base implementation returns the series' resolved Foreground.
| Customizing Label Color |
Copy Code |
|---|---|
public class ColoredColumnDataLabelProvider : BarDataLabelProvider { private static readonly Color PositiveColor = Color.FromRgb(0x68, 0xBC, 0xA0); private static readonly Color NegativeColor = Color.FromRgb(0xE9, 0x7D, 0x51); public override Color GetLabelColor(int index, double yValue) => double.IsNaN(yValue) ? base.GetLabelColor(index, yValue) // leave gaps (NaN) at the series' default color : yValue >= 0 ? PositiveColor : NegativeColor; } | |
| Customizing Label Color |
Copy Code |
|---|---|
<s:FastColumnRenderableSeries Fill="#AA4783D4" Stroke="#4783D4" DataPointWidth="0.6" ShowDataLabels="True"> <s:FastColumnRenderableSeries.DataLabelProvider> <local:ColoredColumnDataLabelProvider /> </s:FastColumnRenderableSeries.DataLabelProvider> </s:FastColumnRenderableSeries> | |
Customizing Label Position
Override GetLabelPosition to take full control of label placement. The base implementation resolves the Auto vertical anchor (peak/valley detection) and applies the configured horizontal/vertical anchors and LabelPadding. Series-specific providers such as BarDataLabelProvider override this to position labels relative to bar, box-plot or error-bar geometry instead of a single point.
| Customizing Label Position |
Copy Code |
|---|---|
public override Point GetLabelPosition(int index, Point anchorPoint, Size textSize, IRenderPassData renderPassData) { // Example: always place the label 10px to the right of the anchor, vertically centered return new Point(anchorPoint.X + 10, anchorPoint.Y - textSize.Height * 0.5); } | |
Fully Custom Providers
Implementing IDataLabelProvider directly (rather than deriving from PointDataLabelProvider) routes the series through the direct-draw path. Labels are drawn exactly as returned: there is no measurement, positioning, caching or skip logic applied that comes from the default implementation of PointDataLabelProvider.
The provider must populate Position, Color, Text and IsVisible on every label it returns. The font is taken from the series style, so font size is uniform across labels.
GenerateDataLabels runs on every render pass on this path, so keep it allocation-light.
Tips and Best Practices
- Subclass PointDataLabelProvider unless you need to own positioning and culling entirely - you get numeric/metadata text, anchors, padding, skip modes and overlap detection for free
- A provider instance always belongs to a single Renderable Series - never share one instance across two series or two surfaces
- Prefer MetadataLabelSelector over a subclass when only the text source differs; reach for GetLabelText, GetLabelColor or GetLabelPosition overrides when the logic depends on more than a static per-point value; implement IDataLabelProvider directly only when you need to bypass measurement, positioning and skip logic altogether
See Also
- DataPoint Labels
- "Use DataLabel Provider" example (SciChart WPF Examples Suite → Style a Chart)