New to Telerik UI for WinForms? Download free 30-day trial

Smart labels

RadChartView provides a built-in mechanism for resolving labels overlapping with the SmartLabelsController. You can add the controller to the Controllers collection of RadChartView and it will optimize the arrangement of the labels in a way that there will be less overlaps.

Add Controller

this.radChartView1.Controllers.Add(new SmartLabelsController());

Me.radChartView1.Controllers.Add(New SmartLabelsController())

Alternatively, you can leave RadChartView do this for you by setting the ShowSmartLabels property:

Set Property

this.radChartView1.ShowSmartLabels = true;

Me.radChartView1.ShowSmartLabels = True

Automatic label placement is one the most complex and time consuming operations in a chart that is NP-hard (http://en.wikipedia.org/wiki/NP-Hard). There is no universal solution for all chart types and there is no solution that can guarantee solution for 100% of the label collisions in every case.

Figure 1: Without Smart Labels

WinForms RadChartView Without Smart Labels

Figure 2: With Smart Labels

WinForms RadChartView With Smart Labels

RadChartView’s SmartLabelsController uses strategies specific to different chart types to resolve label overlaps. Since label overlapping can be quite time consuming with more generalized methods, the more concrete a strategy is the better the performance that can be expected out of it. You do not need to be concerned with the strategy, RadChartView will choose the best of the built-in strategies to be used in your chart.

Figure 3: Without Smart Labels

WinForms RadChartView BarSeries Without Smart Labels

Figure 4: With Smart Labels

WinForms RadChartView BarSeries With Smart Labels

Figure 5: Without Smart Labels

WinForms RadChartView Point Series Without Smart Labels

Figure 6: With Smart Labels

WinForms RadChartView Point Series With Smart Labels

Custom labels strategy

In a specific scenario you may need to control the labels' position. For this purpose, create a derivative of the SmartLabelsStrategyBase class and override its CalculateLocations method. Then, you should use this custom logic in the SmartLabelsController. You can find below a sample code snippet demonstrating how you can position the labels in the top part of the chart:

Custom SmartLabelsStrategy

public class MyStrategy : SmartLabelsStrategyBase
{
    public override void CalculateLocations(Telerik.WinControls.UI.ChartSeriesCollection series, Rectangle plotArea)
    {
        List<LabelElement> labels = new List<LabelElement>();
        List<int> overlaps = new List<int>();
        int x = 70;
        int y = 30;
        int spacing = 6;
        foreach (Telerik.WinControls.UI.ChartSeries chartSeries in series)
        {
            if (!chartSeries.ShowLabels || !chartSeries.IsVisible)
            {
                continue;
            }
            foreach (DataPointElement point in chartSeries.Children)
            {
                LabelElement label = (LabelElement)point.Children[0];
                Rectangle labelRect = ChartRenderer.ToRectangle(label.GetLayoutSlot());
                var newRect = new Rectangle(x, y, labelRect.Width, labelRect.Height);
                x += spacing + labelRect.Width;
                if (x + spacing + labelRect.Width > plotArea.Width - 100)
                {
                    y += spacing + labelRect.Height;
                    x = 70;
                }
                label.SmartRectangle = newRect;
                labels.Add(label);
            }
        }
    }
}
public class MySmartLabelsController : SmartLabelsController
{
    public override void CalculateLabelsPositions(Telerik.WinControls.UI.ChartSeriesCollection series, Rectangle plotArea)
    {
        if (this.Strategy != null)
        {
            this.Strategy.CalculateLocations(series, plotArea);
        }
    }
}

Public Class MyStrategy
    Inherits SmartLabelsStrategyBase
    Public Overrides Sub CalculateLocations(series As Telerik.WinControls.UI.ChartSeriesCollection, plotArea As Rectangle)
        Dim labels As New List(Of LabelElement)()
        Dim overlaps As New List(Of Integer)()
        Dim x As Integer = 70
        Dim y As Integer = 30
        Dim spacing As Integer = 6
        For Each chartSeries As Telerik.WinControls.UI.ChartSeries In series
            If Not chartSeries.ShowLabels OrElse Not chartSeries.IsVisible Then
                Continue For
            End If
            For Each point As DataPointElement In chartSeries.Children
                Dim label As LabelElement = DirectCast(point.Children(0), LabelElement)
                Dim labelRect As Rectangle = ChartRenderer.ToRectangle(label.GetLayoutSlot())
                Dim newRect = New Rectangle(x, y, labelRect.Width, labelRect.Height)
                x += spacing + labelRect.Width
                If x + spacing + labelRect.Width > plotArea.Width - 100 Then
                    y += spacing + labelRect.Height
                    x = 70
                End If
                label.SmartRectangle = newRect
                labels.Add(label)
            Next
        Next
    End Sub
End Class
Public Class MySmartLabelsController
    Inherits SmartLabelsController
    Public Overrides Sub CalculateLabelsPositions(series As Telerik.WinControls.UI.ChartSeriesCollection, plotArea As Rectangle)
        If Me.Strategy IsNot Nothing Then
            Me.Strategy.CalculateLocations(series, plotArea)
        End If
    End Sub
End Class

You must apply the custom SmartLabelsController to RadChartView:

Apply custom strategy

MySmartLabelsController controler = new MySmartLabelsController();
controler.Strategy = new MyStrategy();
this.radChartView1.Controllers.Add(controler);

roperty
        Dim controler As SmartLabelsController = New SmartLabelsController()
        controler.Strategy = New MyStrategy()
        controler.RegisterCustomStrategyWithSeries(GetType(MyStrategy), New List(Of Type)() From {GetType(BarSeries)})
        Me.radChartView1.Controllers.Add(controler)

After the R3 2018 SP1 release, the custom strategy can be applied after setting the Strategy property of the control and after regsitering it with all compatible series:

SmartLabelsController controler = new SmartLabelsController();
controler.Strategy = new MyStrategy();
controler.RegisterCustomStrategyWithSeries(typeof(MyStrategy), new List<Type>() { typeof(BarSeries) });
this.radChartView1.Controllers.Add(controler);

Dim controler As SmartLabelsController = New SmartLabelsController()
controler.Strategy = New MyStrategy()
controler.RegisterCustomStrategyWithSeries(GetType(MyStrategy), New List(Of Type)() From {GetType(BarSeries)})
Me.radChartView1.Controllers.Add(controler)

Before After
WinForms RadChartView Without Custom Smart Label Stategy WinForms RadChartView With Custom Smart Label Stategy

See Also

In this article