Hi!
I would like to have a scatterpoint series with horizontal lines as point template.
Moste important: the width of these horizontal lines must be the width of the ticks on the horizontal axis.
It is supposed to look like a StepLineChart where the verticalrisers are transparent so to speak, so the horizontals forms steps.
2 Answers, 1 is accepted
Hello David,
You can achieve your requirement using the RangeBarSeries. Basically, you can have a bar for each horizontal line. The difference between the bar's low and high values will be very small in order to mimic a line. This difference forms the height of the bar. To make the bar to fill the entire category slot (tick to tick), you can set the GapLength of the horizontal (Categorical or DateTime) axis to 0.
I hope this helps.
Regards,
Martin Ivanov
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
I have come a long way with the point template and a binding for its width, but ATM I'm getting two contentpresenters for each data point. (Using a scatterseries descriptor). any ideas?
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1.TelerikBinning"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<telerik:RadCartesianChart Name="TheChart" Palette="Windows8">
<telerik:RadCartesianChart.Resources />
<telerik:RadCartesianChart.HorizontalAxis>
<telerik:LinearAxis Maximum="{Binding MaximumXTick}" />
</telerik:RadCartesianChart.HorizontalAxis>
<telerik:RadCartesianChart.VerticalAxis>
<telerik:LinearAxis />
</telerik:RadCartesianChart.VerticalAxis>
<telerik:RadCartesianChart.SeriesProvider>
<telerik:ChartSeriesProvider Source="{Binding Series}">
<telerik:ChartSeriesProvider.SeriesDescriptors>
<!-- Central tendency -->
<telerik:ScatterSeriesDescriptor ItemsSourcePath="CentralTendencyPoints"
XValuePath="XValue"
YValuePath="YValue">
<telerik:ScatterSeriesDescriptor.Style>
<Style TargetType="telerik:ScatterPointSeries">
<Setter Property="PointTemplate">
<Setter.Value>
<DataTemplate>
<Border Width="{Binding Path=TendencyWidth,
RelativeSource={RelativeSource AncestorType=UserControl},
FallbackValue=500}"
BorderBrush="BlueViolet"
BorderThickness="0,2,0,0" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</telerik:ScatterSeriesDescriptor.Style>
</telerik:ScatterSeriesDescriptor>
</telerik:ChartSeriesProvider.SeriesDescriptors>
</telerik:ChartSeriesProvider>
</telerik:RadCartesianChart.SeriesProvider>
</telerik:RadCartesianChart>
</Grid>
</UserControl>
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Telerik.Windows.Controls.ChartView;
using WpfApp1.Annotations;
namespace WpfApp1.TelerikBinning
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
SizeChanged += Window1_SizeChanged;
((LinearAxis)TheChart.HorizontalAxis).ActualRangeChanged += (x, y) => UpdateCentralTendency();
SetData();
DataContext = this;
}
public List<DataSerie> Series { get; set; }
private void SetData()
{
Series = new List<DataSerie>
{
new DataSerie()
{
CentralTendencyPoints = new List<CentralTendencyPoint>
{
new CentralTendencyPoint(){XValue = 2, YValue = 2}
}
},
new DataSerie()
{
CentralTendencyPoints = new List<CentralTendencyPoint>
{
new CentralTendencyPoint(){XValue = 3, YValue = 3}
}
},
new DataSerie()
{
CentralTendencyPoints = new List<CentralTendencyPoint>
{
new CentralTendencyPoint(){XValue = 4, YValue = 6}
}
}
};
}
public double MaximumXTick => 5;
public double TendencyWidth { get; set; }
private int CentralTendencyCount => 2;
private void Window1_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateCentralTendency();
}
private void UpdateCentralTendency()
{
var range = ((LinearAxis)TheChart.HorizontalAxis).ActualRange;
var stepCount = range.Maximum - range.Minimum;
if (stepCount != 0)
{
TendencyWidth = TheChart.PlotAreaClip.Width / stepCount;
OnPropertyChanged(nameof(TendencyWidth));
}
}
public double X1 { get; set; }
public double X2 => 2 * X1;
public double ContainerWidth => 2 * X1;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class DataSerie
{
public List<CentralTendencyPoint> CentralTendencyPoints { get; set; }
}
public class CentralTendencyPoint
{
public double XValue { get; set; }
public double YValue { get; set; }
}
}
This happens because the chart is caching the size of the ContentPresenter generated for the element in the PointTemplate. This is a performance optimization, but it slightly limits the size updates in the PointTemplate element. A standard binding (directly to the underlying view model) of the Width and Height properties should work initially, but won't work if you update it at runtime. In your case, the initial binding won't work either, because of the RelativeSource usage. This delays the binding and it gets evaluated after the size is cached.
Any change in the chart's API will update the size cache. This is why the approach with resetting the PointTemplate works.
HACK:
I can make it update the databinding if I attach an eventhandler and in there I set the point template to null and then set it back to what it was!