Dynamic Number of Series (ChartSeriesProvider)

In this help topic, you will learn what mechanism ChartView provides for automatic series generation.

Overview

RadCartesianChart and RadPolar chart can create a dynamic number of series depending on the data (collection of collections). To take advantage of this feature, you need to create a ChartSeriesProvider object. This will be the object that receives the data and holds the ChartSeriesDescriptors – objects that define the specific properties of the dynamically generated series.

The series provider uses descriptor objects to define the type and visual apperance of the series. Depending on the series type that you want to use, you can define different descriptors.

Series Descriptor
Categorical Series (BarSeries, LineSeries, SplineSeries, AreaSeries, SplineAreaSeries) CategoricalSeriesDescriptor
Financial Series (OhlcSeries, CandlestickSeries) OhlcSeriesDescriptor
Scatter Series (ScatterPointSeries, ScatterLineSeries, ScatterSplineSeries, ScatterAreaSeries, ScatterSplineAreaSeries) ScatterSeriesDescriptor
Polar Series (PolarPointSeries, PolarLineSeries, PolarAreaSeries) PolarSeriesDescriptor
Radar Series (RadarPointSeries, RadarLineSeries, RadarAreaSeries) RadarSeriesDescriptor
All Series Types ChartSeriesDescriptor

ChartSeriesDescriptor

ChartSeriesProvider allows you to use a generic descriptor that gives you more flexibility and it can be used with all chart series. This is the base ChartSeriesDescriptor class. The descriptor doesn't expose value properties and it does not expect a specific type of series, so you can define all you need in its style.

Example 1: A ChartSeriesDescriptor that describes a RangeSeries

<telerik:ChartSeriesDescriptor ItemsSourcePath="MyDataPointsCollection">
    <telerik:ChartSeriesDescriptor.Style>
        <Style TargetType="telerik:RangeSeries">
            <Setter Property="CategoryBinding" Value="MyCategory"/>
            <Setter Property="HighBinding" Value="MyHighValue"/>
            <Setter Property="LowBinding" Value="MyLowValue"/>                                    
        </Style>
    </telerik:ChartSeriesDescriptor.Style>
</telerik:ChartSeriesDescriptor>

In this case, the TargetType of the descriptor determines the type of the series that will be created.

If you use NoXaml dlls and the implicit styles theming mechanism you will need to base the Style of the ChartSeriesDescriptor on the default style of the series. In the example above you have to set the following property of the Style - BasedOn="{StaticResource RangeSeriesStyle}". The same naming convention <series name>Style is applicable for all series types, for example, LineSeriesStyle, BarSeriesStyle, PointSeriesStyle, etc. If you don't set the BasedOn attribute when using NoXaml dlls, the series won't display any data points.

Properties

Important properties of ChartSeriesDescriptor:

  • ItemsSourcePath: A property of type string that gets or sets the path to the collection property that will feed the generated series.

  • TypePath: A property of type string that gets or sets the path to the property that indicates the series type that needs to be created.

  • Style: A property of type Style that gets or sets the style that describes the appearance of the series that are to be created. If no TypePath is specified, the TargetType property of the style object is used to generate the desired series.

  • CollectionIndex: A property of type int that gets or sets the index within the Source collection of data (view models) for which the current descriptor should be used. This property is useful when, for example, a BarSeries needs to be generated for the first data entry and LineSeries for the rest of the entries.

Type-specific properties:

  • CategoricalSeriesDescriptor

    • CategoryPath: A property of type string that sets or gets the path to the Category property of the data item.
    • ValuePath: A property of type string that sets or gets the path to the Value property of the data item.
  • OhlcSeriesDescriptor

    • OpenPath: A property of type string that sets or gets the path to the Open value of the data item.
    • HighPath: A property of type string that sets or gets the path to the High value of the data item.
    • LowPath: A property of type string that sets or gets the path to the Low value of the data item.
    • ClosePath: A property of type string that sets or gets the path to the Close value of the data item.
  • PolarSeriesDescriptor

    • ValuePath: A property of type string that sets or gets the path to the Value of the data item.
    • Anglepath: A property of type string that sets or gets the path to the Angle value of the data item.
  • RadarSeriesDescriptor

    • CategoryPath: A property of type string that sets or gets the path to the Category of the data item.
    • ValuePath: A property of type string that sets or gets the path to the Value of the data item.

Events

ChartSeriesProvider expose a single event - SeriesCreated. The event occurs when a series is created. It allows for the series to be additionally set up or completely replaced.

The event arguments are of type ChartSeriesCreatedEventArgs and expose the following properties:

  • Series: A property of type ChartSeries that holds the created series.
  • Context: A property of type object that holds the model of the series.

This event may be raised with the series being null (for example, in cases when a suitable descriptor was not found). In such a case, this event can still be used to create and set up a new series.

Code Example

In the following example, the chart is populated by a collection of 3 items, thus creating 3 series. There is a CategoricalSeriesDescriptor with CollectionIndex=2 and a style with TargetType="LineSeries". This effectively means that there will be a LineSeries, populated by the third item in the collection. There is another CategoricalSeriesDescriptor which is responsible for creating BarSeries for the rest of the items in the collection.

Example 2: A sample chart definition with its SeriesProvider set

<telerik:RadCartesianChart Palette="Flower">
    <telerik:RadCartesianChart.HorizontalAxis>
        <telerik:CategoricalAxis />
    </telerik:RadCartesianChart.HorizontalAxis>
    <telerik:RadCartesianChart.VerticalAxis>
        <telerik:LinearAxis />
    </telerik:RadCartesianChart.VerticalAxis>

    <telerik:RadCartesianChart.SeriesProvider>
        <telerik:ChartSeriesProvider Source="{Binding Data}">
            <telerik:ChartSeriesProvider.SeriesDescriptors>
                <telerik:CategoricalSeriesDescriptor CategoryPath="Category" 
                                                        ValuePath="Value" 
                                                        ItemsSourcePath="Items" />
                <telerik:CategoricalSeriesDescriptor CategoryPath="Category"
                                                        ValuePath="Value"
                                                        ItemsSourcePath="Items" 
                                                        CollectionIndex="2">
                    <telerik:CategoricalSeriesDescriptor.Style>
                        <Style TargetType="telerik:LineSeries">
                            <Setter Property="StrokeThickness" Value="4" />
                        </Style>
                    </telerik:CategoricalSeriesDescriptor.Style>
                </telerik:CategoricalSeriesDescriptor>
            </telerik:ChartSeriesProvider.SeriesDescriptors>
        </telerik:ChartSeriesProvider>
    </telerik:RadCartesianChart.SeriesProvider>
</telerik:RadCartesianChart>

Example 3: The chart's view models set up

public class DataItem
{
    public string Category { get; set; }

    public double Value { get; set; }
}

public class SeriesViewModel
{
    public string SeriesType { get; set; }

    public ObservableCollection<DataItem> Items { get; set; }
}

public class MainViewModel
{
    public ObservableCollection<SeriesViewModel> Data
    {
        get;
        set;
    }

    public MainViewModel()
    {
        this.Data = new ObservableCollection<SeriesViewModel>()
        {
            new SeriesViewModel()
            {
                SeriesType = "Bar",
                Items = new ObservableCollection<DataItem>()
                {
                    new DataItem() { Category = "A", Value = 5},
                    new DataItem() { Category = "B", Value = 7},
                    new DataItem() { Category = "C", Value = 6},
                    new DataItem() { Category = "D", Value = 8}
                }
            },
            new SeriesViewModel()
            {
                SeriesType = "Bar",
                Items = new ObservableCollection<DataItem>()
                {
                    new DataItem() { Category = "A", Value = 15},
                    new DataItem() { Category = "B", Value = 18},
                    new DataItem() { Category = "C", Value = 19},
                    new DataItem() { Category = "D", Value = 23}
                }
            },
            new SeriesViewModel()
            {
                SeriesType = "Line",
                Items = new ObservableCollection<DataItem>()
                {
                    new DataItem() { Category = "A", Value = 21},
                    new DataItem() { Category = "B", Value = 25},
                    new DataItem() { Category = "C", Value = 26},
                    new DataItem() { Category = "D", Value = 25}
                }
            }
        };
    }
}
Public Class DataItem
    Public Property Category() As String

    Public Property Value() As Double
End Class


Public Class SeriesViewModel
    Public Property SeriesType() As String

    Public Property Items() As ObservableCollection(Of DataItem)
End Class

Public Class MainViewModel
    Public Property Data() As ObservableCollection(Of SeriesViewModel)

    Public Sub New()
        Me.Data = New ObservableCollection(Of SeriesViewModel)() _
            From {
                New SeriesViewModel() With {
                    .SeriesType = "Bar",
                    .Items = New ObservableCollection(Of DataItem)() From {
                        New DataItem() With {
                            .Category = "A",
                            .Value = 5
                        },
                        New DataItem() With {
                            .Category = "B",
                            .Value = 7
                        },
                        New DataItem() With {
                            .Category = "C",
                            .Value = 6
                        },
                        New DataItem() With {
                            .Category = "D",
                            .Value = 8
                        }
                    }
                },
                New SeriesViewModel() With {
                    .SeriesType = "Bar",
                    .Items = New ObservableCollection(Of DataItem)() From {
                        New DataItem() With {
                            .Category = "A",
                            .Value = 15
                        },
                        New DataItem() With {
                            .Category = "B",
                            .Value = 18
                        },
                        New DataItem() With {
                            .Category = "C",
                            .Value = 19
                        },
                        New DataItem() With {
                            .Category = "D",
                            .Value = 23
                        }
                    }
                },
                New SeriesViewModel() With {
                    .SeriesType = "Line",
                    .Items = New ObservableCollection(Of DataItem)() From {
                        New DataItem() With {
                            .Category = "A",
                            .Value = 21
                        },
                        New DataItem() With {
                            .Category = "B",
                            .Value = 25
                        },
                        New DataItem() With {
                            .Category = "C",
                            .Value = 26
                        },
                        New DataItem() With {
                            .Category = "D",
                            .Value = 25
                        }
                    }
                }
            }
    End Sub
End Class

Figure 1: Dynamic number of series generated using SeriesProvider

Rad Chart View-chartseriesprovider-0

You can find runnable examples that demonstrate the SeriesProvider in our GitHub SDK repository. There are a couple examples that you can find under the following directories in the repository - ChartView/SL/SeriesProvider and ChartView/SL/SeriesDescriptorSelector

See Also

In this article
Not finding the help you need? Improve this article