RadChartView ScatterPointSeries with horizontal lines

2 Answers 133 Views
Chart
David
Top achievements
Rank 1
Iron
David asked on 17 Aug 2021, 03:39 PM | edited on 18 Aug 2021, 06:19 AM

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

Sort by
0
Martin Ivanov
Telerik team
answered on 20 Aug 2021, 08:20 AM

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.

David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 08:24 AM

Thank you will have a look
David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 09:01 AM

But we use a cartesian chart with linear axis, The bar series needs Categorical axes!
David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 09:05 AM

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?

 

David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 09:13 AM

If  I just set "pointsize" I get only one contentpresenter. But since I need a line, the default ellipse is not good enough.
David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 09:36 AM

<UserControl x:Class="WpfApp1.TelerikBinning.UserControl1"
             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>
David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 09:36 AM

using System;
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; }
    }
}
David
Top achievements
Rank 1
Iron
commented on 20 Aug 2021, 12:57 PM

My problem seems to be that the chart will not refresh the Border width of the object in  the pointtemplate.
Martin Ivanov
Telerik team
commented on 25 Aug 2021, 08:10 AM

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.

0
David
Top achievements
Rank 1
Iron
answered on 23 Aug 2021, 08:08 AM

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!

Tags
Chart
Asked by
David
Top achievements
Rank 1
Iron
Answers by
Martin Ivanov
Telerik team
David
Top achievements
Rank 1
Iron
Share this question
or