1. How can I apply Styles to the two different types of series? CategoricalSeriesDescriptor only takes a single Style, and that Style only accepts Properties of the specified TargetType; I can't figure out how to set styles for each series type.
2. (How) can I use a converter to supply the ChartView with the Series Type so that the ViewModel in MVVM doesn't have to supply telerik types to the View? TypePath doesn't allow a binding (I get "System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element." if I try) so I can't apply the "Converter" tag.
If there's a better way to display variable numbers of series using 2 different series types please do point it out as well.
Thanks,
Louis
18 Answers, 1 is accepted

I have the same issue.
Please advice.
Yoni

While waiting for an official response, I did manage to figure out how to apply the styles to different Series types automatically; Define them as Resources of the Chart with the TargetType set (but without IDs), and they will automatically apply based on the TypePath. This won't work if you want different styles for the same Series type, but it works for what I need.
I also found another potential problem in doing this (if you're doing it the way I tried to, with 2 different types underlying the different Series); the objects that supply the ItemsSource must all be of the same actual type. You cannot have different types with a common base class or that support a common interface, as the Grid seems to use reflection to create its own internal storage of the list, and types it based on the actual type of object you pass to it in the first Series (regardless of what type your Collection exposes). I handled this by using an adapter class that can store either type of object, and presents the relevant fields (including graph type) through its own properties. I did all this in the code-behind (which is quite ugly) so it's part of the View, as it really is view-implementation specific.
I'd still like to hear if there's a way to adapt the graph type in XAML or in a better way that doesn't lead to such a big layer in the View itself.
Hope this helps,
Louis
P.S. Here's a simplified version of what I ended up with, for your reference:
<
telerik:RadCartesianChart
...>
<
telerik:RadCartesianChart.Resources
>
<
Style
TargetType
=
"telerik:LineSeries"
>
<
Setter
Property
=
"StrokeThickness"
Value
=
"2"
/>
<
Setter
Property
=
"CategoryBinding"
Value
=
"{StaticResource timeBinding}"
/>
<
Setter
Property
=
"ValueBinding"
Value
=
"{StaticResource rateBinding}"
/>
</
Style
>
<
Style
TargetType
=
"telerik:BarSeries"
>
<
Setter
Property
=
"CategoryBinding"
Value
=
"{StaticResource timeBinding}"
/>
<
Setter
Property
=
"ValueBinding"
Value
=
"{StaticResource rateBinding}"
/>
<
Setter
Property
=
"PointTemplate"
Value
=
"{StaticResource HistoricalPointDataTemplate}"
/>
</
Style
>
</
telerik:RadCartesianChart.Resources
>
...
<
telerik:RadCartesianChart.SeriesProvider
>
<
telerik:ChartSeriesProvider
x:Name
=
"ChartProvider"
Source
=
"{Binding Path=GraphSeries,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
>
<!-- this is to point to the code-behind layer instead of the VM -->
<
telerik:ChartSeriesProvider.SeriesDescriptors
>
<
telerik:CategoricalSeriesDescriptor
ItemsSourcePath
=
"Data"
TypePath
=
"SeriesType"
/>
</
telerik:ChartSeriesProvider.SeriesDescriptors
>
</
telerik:ChartSeriesProvider
>
</
telerik:RadCartesianChart.SeriesProvider
>
</
telerik:RadCartesianChart
>
Louis, I think that the answer to your original question is SeriesDescriptorSelector. You can implement your own MyChartSeriesDescriptorSelector where you have set up the series descriptors and return the one you desire in the SelectDescriptor override.
As far as the solution you have found - great job! You are correct about the limitation - if you need two different bar series style - this work-around will not fulfill the requirements.
I am unsure what you mean by "You cannot have different types with a common base class". It is possible to do that but the code is optimized for scenarios where all items are of the same type. Pehaps you can use the GenericDataPointBinding instead of the PropertyNameDataPoingBinding which is more flexible and does not require such an optimization (due to its nature), and is actually faster anyway.
I have attached a small project to demonstrate that the chart renders correctly two bar series that share the same property name data point bindings and use two different ItemsSources as you have described. If you experience any issues I will ask that you provide more information on the matter.
Regards,
Petar Marchev
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>

What would be very useful in my case would be to be able to specify two different ChartSeriesProviders in a single chart; correct me if I'm wrong, but I don't think this is possible. If I could do this, it would use two different Sources and not suffer from the problem.
The biggest outstanding question I have is #2 from my original post; I'd like to be able to use a converter for the TypePath as it's not reasonable to expose Telerik series types from a ViewModel.
Thanks again,
Louis
It is true that the current implementation of the chart does not support two series providers, unless you toggle two different providers in your app. And it is also true that it is not possible to have a converter for the TypePath property as this property specifies the name of the property from which the series type is expected. I have forwarded this to our developers and they will try and find a way to remove this limitation.
I am still unsure what is the scenario that you describe so I will ask that you send us a small project that demonstrates this so that we can investigate.
Regards,
Petar Marchev
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>

I've come up with minimal example of my issues for your reference:
MainWindow.xaml:
<
Window
x:Class
=
"TwoDynamic.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
Title
=
"MainWindow"
Height
=
"350"
Width
=
"525"
>
<
Window.Resources
>
<
ResourceDictionary
>
<
DataTemplate
x:Key
=
"PointDataTemplate"
>
<
Ellipse
Width
=
"4"
Height
=
"4"
Fill
=
"Red"
/>
</
DataTemplate
>
</
ResourceDictionary
>
</
Window.Resources
>
<
Grid
>
<
telerik:RadCartesianChart
>
<
telerik:RadCartesianChart.Resources
>
<
Style
TargetType
=
"telerik:LineSeries"
>
<
Setter
Property
=
"StrokeThickness"
Value
=
"2"
/>
<
Setter
Property
=
"Stroke"
Value
=
"Blue"
/>
</
Style
>
<
Style
TargetType
=
"telerik:BarSeries"
>
<
Setter
Property
=
"PointTemplate"
Value
=
"{StaticResource PointDataTemplate}"
/>
<
Setter
Property
=
"CombineMode"
Value
=
"None"
/>
</
Style
>
</
telerik:RadCartesianChart.Resources
>
<
telerik:RadCartesianChart.Grid
>
<
telerik:CartesianChartGrid
MajorLinesVisibility
=
"XY"
/>
</
telerik:RadCartesianChart.Grid
>
<
telerik:RadCartesianChart.HorizontalAxis
>
<
telerik:DateTimeContinuousAxis
LabelFitMode
=
"Rotate"
LabelFormat
=
"MMM-dd"
/>
</
telerik:RadCartesianChart.HorizontalAxis
>
<
telerik:RadCartesianChart.VerticalAxis
>
<
telerik:LinearAxis
/>
</
telerik:RadCartesianChart.VerticalAxis
>
<
telerik:RadCartesianChart.SeriesProvider
>
<
telerik:ChartSeriesProvider
Source
=
"{Binding Path=Series}"
>
<
telerik:ChartSeriesProvider.SeriesDescriptors
>
<
telerik:CategoricalSeriesDescriptor
ItemsSourcePath
=
"Data"
TypePath
=
"SeriesType"
CategoryPath
=
"Date"
ValuePath
=
"Value"
/>
</
telerik:ChartSeriesProvider.SeriesDescriptors
>
</
telerik:ChartSeriesProvider
>
</
telerik:RadCartesianChart.SeriesProvider
>
</
telerik:RadCartesianChart
>
</
Grid
>
</
Window
>
MainWindow.xaml.cs:
using
System.Windows;
namespace
TwoDynamic
{
public
partial
class
MainWindow : Window
{
public
MainWindow()
{
InitializeComponent();
DataContext =
new
ViewModel();
}
}
}
And ViewModel.cs:
using
System;
using
System.Collections.ObjectModel;
using
Telerik.Windows.Controls.ChartView;
// Should not have this in VM layer!
namespace
TwoDynamic
{
public
class
DataPoint
{
public
DateTime Date {
get
;
set
; }
public
double
Value {
get
;
set
;}
}
public
abstract
class
SeriesBase
{
public
abstract
ObservableCollection<DataPoint> Data {
get
;
set
; }
// This DOES NOT BELONG in the ViewModel! TypePath really needs
// a converter so this can provide a generic type, and have the
// Telerik-specific type supplied in the View layer.
public
abstract
Type SeriesType {
get
; }
}
public
class
PointData: SeriesBase
{
public
override
Type SeriesType {
get
{
return
typeof
(BarSeries); } }
public
override
ObservableCollection<DataPoint> Data {
get
;
set
; }
}
public
class
LineData : SeriesBase
{
public
override
Type SeriesType {
get
{
return
typeof
(LineSeries); } }
public
override
ObservableCollection<DataPoint> Data {
get
;
set
; }
}
public
class
ViewModel
{
private
Random _Random;
private
ObservableCollection<SeriesBase> _Series;
public
ObservableCollection<SeriesBase> Series {
get
{
return
_Series; } }
public
ViewModel()
{
_Random =
new
Random();
_Series =
new
ObservableCollection<SeriesBase>();
// In reality there would be a variable number of these.
_Series.Add(
new
PointData() { Data = GenerateSomeData() });
_Series.Add(
new
PointData() { Data = GenerateSomeData() });
// I can either add PointData items, or LineData items, but not both
//_Series.Add(new LineData() { Data = GenerateSomeData() });
//_Series.Add(new LineData() { Data = GenerateSomeData() });
}
private
ObservableCollection<DataPoint> GenerateSomeData()
{
ObservableCollection<DataPoint> newCollection =
new
ObservableCollection<DataPoint>();
for
(
int
i = 0; i < 10; i++)
newCollection.Add(
new
DataPoint() { Date =
new
DateTime(2012, 12, 31).AddDays(i), Value = _Random.Next(100) });
return
newCollection;
}
}
}
My problem #1 is that in ViewModel, I can add any number of EITHER LineData OR PointData items to the list and it all works fine. However, even though they're both SeriesBase types which is what is exposed in the collection, if I add both it throws the exception:
System.InvalidCastException was unhandled
HResult=-2147467262
Message=Unable to cast
object
of type
'TwoDynamic.LineData'
to type
'TwoDynamic.PointData'
.
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at Telerik_DynamicGetter_SeriesType(Object )
at Telerik.Windows.Controls.ChartView.ChartSeriesDescriptor.ResolveType(Object context)
in
c:\TB\221\WPF_Scrum\Release_WPF\Sources\Development\Controls\Chart\Visualization\DataBinding\DynamicSeries\SeriesDescriptors\ChartSeriesDescriptor.cs:line 178
My real LineData and PointData classes are of course much more complicated, and have lots of distinct functionality relevant to the actual data that is being displayed. I have worked around this by creating an adapter class that can hold either of these types of objects, and whose properties return the contained object's values, but this is a pretty ugly hack.
The second issue I think you already understand, and that is that there should be no references to Telerik types in the ViewModel, but there's no (clean) way to use the TypePath setting without doing so (thus the need for the converter).
Does that clear things up?
Thanks,
Louis
Thank you for the attached code snippets, I was able to create a new project based on it and reproduced the exception in mind. I have logged this for investigation and you can find it in our system and I have also updated your Telerik points as a sign of gratitude.
As a work-around I can suggest you slightly modify the SeriesBase class and its inheritors. I have attached a project to demonstrate the change in mind and it is essentially this:
public
class
SeriesBase
{
public
ObservableCollection<DataPoint> Data {
get
;
set
; }
public
Type SeriesType {
get
{
return
this
.SeriesTypeOverride; } }
public
virtual
Type SeriesTypeOverride {
get
{
return
null
; } }
}
public
class
PointData : SeriesBase
{
public
override
Type SeriesTypeOverride {
get
{
return
typeof
(BarSeries); } }
}
I apologize for not being clear enough in my previous post - the SeriesProvider is a property of the chart and you can have only one provider per chart at a time.
I will again suggest that you go with the descriptor selector as I think this is what will solve all the issues you are experiencing.
"I have worked around this by creating an adapter class .... but this is a pretty ugly hack."
I think that this is a great solution as it would allow you to have the view models unchanged and Telerik agnostic, while this adapter class can wrap the original view model and have Telerik's controls cognition.
I fully agree that there is need of a converter and we have plans to enhance the series provider in this direction.
Regards,
Petar Marchev
Telerik
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>

I agree with you that the SeriesDescriptorSelector would work great, although for my purposes just the un-ID'd TargetType'd styles work fine since I don't need multiple styles for the same TargetType.
Thank you for all the help. I think we're good (with the issues in this thread at least) pending the future Abstract base class and converter enhancements.
Louis

Hi Petar,
I made a solution based upon your latest post with sample project 755202.2.zip where the charts gets generated dynamically.
At this point the solution works.
Although I was able to bind the color with mvvm to a property of the model for a lineserie, I was not able to get it up and running for a bar serie.
Below you can find the styling code.
<
telerik:RadCartesianChart
x:Name
=
"Seriesgraph"
HoverMode
=
"FadeOtherSeries"
Background
=
"WhiteSmoke"
Grid.Column
=
"2"
Margin
=
"12.8,10,10,10"
Grid.Row
=
"5"
Grid.ColumnSpan
=
"5"
Grid.RowSpan
=
"3"
>
<
telerik:RadCartesianChart.Resources
>
<
Style
TargetType
=
"telerik:LineSeries"
BasedOn
=
"{StaticResource lineSeriesStyle}"
>
<
Setter
Property
=
"StrokeThickness"
Value
=
"{Binding Dikte}"
/>
<
Setter
Property
=
"behavior:ChartUtilitiesAttachedProperty.SeriesLegendSettings"
Value
=
"{Binding PlcVariableName}"
/>
<
Setter
Property
=
"Stroke"
Value
=
"{Binding Color}"
/>
<
Setter
Property
=
"ShowLabels"
Value
=
"True"
/>
<
Setter
Property
=
"DashArray"
Value
=
"0.1"
/>
</
Style
>
<
Style
TargetType
=
"telerik:BarSeries"
BasedOn
=
"{StaticResource BarSeriesStyle}"
>
<
Setter
Property
=
"CombineMode"
Value
=
"Stack"
/>
<
Setter
Property
=
"behavior:ChartUtilitiesAttachedProperty.SeriesLegendSettings"
Value
=
"{Binding PlcVariableName}"
/>
<
Setter
Property
=
"ShowLabels"
Value
=
"True"
/>
<
Setter
Property
=
"PointTemplate"
>
<
Setter.Value
>
<
DataTemplate
>
<
Rectangle
Fill
=
"{Binding Color}"
/>
</
DataTemplate
>
</
Setter.Value
>
</
Setter
>
</
Style
>
</
telerik:RadCartesianChart.Resources
>
Can you guide me towards a solution, many thanks in advance.
Kind Regards
Frederic

Hi Frederic,
Are you getting any binding errors in the output? My implementation is a bit different, but I had to use Fill="{Binding Path=DataItem.Color}" to get to the Color property on my VMs.
Louis
Hi Louis,
I was able to set the color of barseries as defined in the viewmodel. Thank you for sharing this information.
Since I am doing more or less the same as your solution, perhaps you can help with an additional topic?
I'm able to display a legend for all chart types except for the bar series.
I found a post here that reveals that we cannot using a pointtemplate and legend item together:
When you use a PointTemplate, the chart does not know how you color the visuals and it does not know how to chose a color for the legend item. I think you should try using the DefaultVisualStyle instead of the PointTemplate for the BarSeries. This way the legend item will get its color automatically.
Petar Marchev
Telerik
Where you able to get it up and running in your solution? Any ideas in resolving this?
Many thanks in advance
Frederic

Sorry Frederic, I don't have any experience with using legends on the Telerik ChartView; we create our own legend outside the chart, which might be an option for you as well.
Louis

Thanks for the suggestion, a solid alternative.
Kind regards
Frederic
You should be able to use the DefaultVisualStyle property instead of the PointTemplate for the bar series. It should be a style targeting a Border element, and the DataContext of this Border is the DataPoint, so you can use a setter for the Background of the Border.
Regards,
Petar Marchev
Telerik

Hi Petar,
Thank you for the suggestions.
We have implemented the suggestions and now we have legenditems with corresponding color for the bar series aswell.
Kind regards
Frederic

Hi Petar,
I am doing exactly same as this post(/multiple-series-types-with-chartseriesprovider-and-typepath) with one change and I am using RangeBarSeries Type instead of BarSeries.But i am getting compile error as below.Please advice the right approach to add mixed series.
Additional information: Unable to cast object of type 'Telerik.Windows.Controls.ChartView.RangeBarSeries' to type 'Telerik.Windows.Controls.ChartView.CategoricalSeries'.
I will ask you to open a new thread because we prefer to keep different questions separated instead of cluttering a single forum post. Thank you for understanding.
Regards,
Petar Marchev
Telerik
