Customizing Scatter Points
RadChartView allows you to set custom shape for the Scatter points (items of the ScatterPointSeries) via DataTemplate. However there are cases where we would like each point in our scatter series to have different shape or color. This is where you should use the PointTemplateSelector property.
The following example demonstrates how you can add a custom Framework Element (Rectangle, Ellipse and etc.) to present the scatter points and set different color per each point based on condition defined by PointTemplateSelector.
We'll get started with a class with two properties - X and Y. They will be used to represent the coordinates of each point on the Chart. We'll also need a method that will return Brush with color based on the YValue of our business objects.
public class ChartData
{
private readonly Brush Red = new SolidColorBrush(Colors.Red);
private readonly Brush Orange = new SolidColorBrush(Colors.Orange);
private readonly Brush Green = new SolidColorBrush(Colors.Green);
public ChartData(double x, double y)
{
this.XValue = x;
this.YValue = y;
}
public double XValue { get; set; }
public double YValue { get; set; }
public Brush Brush
{
get
{
if (this.YValue < 102)
{
return Red;
}
else if (this.YValue < 105)
{
return Orange;
}
else
{
return Green;
}
}
}
}Our next task is to create a ViewModel. For the purpose - create new class that inherits the ViewModelBase abstract class.
ViewModelBase class is part of the Telerik.Windows.Controls.dll
What we'll need to add in it - a property of type List of ChartData. It will be used as data source for our scatterpoint series. We'll populate the newly created collection with some data in a method that is called GetData. In the constructor of the ViewModel class call the GetData method we created in our ChartData class.
public class ViewModel : ViewModelBase
{
private List<ChartData> data;
public ViewModel()
{
this.Data = this.GetData();
}
public List<ChartData> Data
{
get
{
return this.data;
}
set
{
if (this.data != value)
{
this.data = value;
this.OnPropertyChanged("Data");
}
}
}
private List<ChartData> GetData()
{
List<ChartData> data = new List<ChartData>();
data.Add(new ChartData(0.1, 100));
data.Add(new ChartData(0.1, 101));
data.Add(new ChartData(11, 106));
data.Add(new ChartData(101, 104));
data.Add(new ChartData(101, 108));
return data;
}
}It's time to create our ScatterPoint series in XAML and populate it with data. It is beyond the scope of this topic to describe how you can populate the series. Please refer to our Create Data-Bound Chart topic for details.
<UserControl.DataContext>
<local:ViewModel />
</UserControl.DataContext>
<Grid>
<telerik:RadCartesianChart x:Name="RadChart1">
<telerik:ScatterPointSeries XValueBinding="XValue"
YValueBinding="YValue"
ItemsSource="{Binding Data}" >
<telerik:ScatterPointSeries.PointTemplate>
<DataTemplate>
<Ellipse Width="10"
Height="10"
Fill="{Binding DataItem.Brush}"/>
</DataTemplate>
</telerik:ScatterPointSeries.PointTemplate>
</telerik:ScatterPointSeries>
<telerik:RadCartesianChart.HorizontalAxis>
<telerik:LogarithmicAxis Minimum="0.01" />
</telerik:RadCartesianChart.HorizontalAxis>
<telerik:RadCartesianChart.VerticalAxis>
<telerik:LinearAxis />
</telerik:RadCartesianChart.VerticalAxis>
<telerik:RadCartesianChart.Grid>
<telerik:CartesianChartGrid MajorLinesVisibility="XY" />
</telerik:RadCartesianChart.Grid>
</telerik:RadCartesianChart>
</Grid>
Up to now you should have a ScatterPoint series with elliptical shape where the color of each point comes from a propery of the underlying Business object.

For our scenario where we would like different shape for the pointmarks, this means that we should create different DataTemplates. We need to create a selector class which will dictate an ellipse or rectangle template to be set per condition. It should inherit the DataTemplateSelector class and define the condition by overriding its SelectTemplate method. The source code is below:
<UserControl.Resources>
<local:ScatterPointTemplateSelector x:Key="templateSelector" />
</UserControl.Resources>
<UserControl.DataContext>
<local:ViewModel />
</UserControl.DataContext>
<Grid>
<telerik:RadCartesianChart x:Name="RadChart1">
<telerik:RadCartesianChart.Resources>
<DataTemplate x:Key="ellipseTemplate">
<Ellipse Height="10" Width="10" Fill="{Binding DataItem.Brush}" />
</DataTemplate>
<DataTemplate x:Key="rectangleTemplate">
<Rectangle Height="10" Width="10" Fill="{Binding DataItem.Brush}" />
</DataTemplate>
</telerik:RadCartesianChart.Resources>
<telerik:ScatterPointSeries XValueBinding="XValue"
YValueBinding="YValue"
ItemsSource="{Binding Data}"
PointTemplateSelector="{StaticResource templateSelector}" />
<telerik:RadCartesianChart.HorizontalAxis>
<telerik:LogarithmicAxis Minimum="0.01" />
</telerik:RadCartesianChart.HorizontalAxis>
<telerik:RadCartesianChart.VerticalAxis>
<telerik:LinearAxis />
</telerik:RadCartesianChart.VerticalAxis>
<telerik:RadCartesianChart.Grid>
<telerik:CartesianChartGrid MajorLinesVisibility="XY" />
</telerik:RadCartesianChart.Grid>
</telerik:RadCartesianChart>
</Grid>
public class ScatterPointTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var scatterPoint = (ScatterDataPoint)item;
var itemIndex = scatterPoint.Index;
var series = container as ScatterPointSeries;
var dataPoint = series.DataPoints[itemIndex];
var chart = series.GetVisualParent<RadCartesianChart>();
if (dataPoint.YValue > 105)
{
return chart.Resources["ellipseTemplate"] as DataTemplate;
}
else
{
return chart.Resources["rectangleTemplate"] as DataTemplate;
}
}
}