This is a migrated thread and some comments may be shown as answers.

Columns overlapping on DateTimeContinuousAxis

5 Answers 204 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Mitchell
Top achievements
Rank 1
Mitchell asked on 12 Jan 2014, 09:02 PM

I'm creating a column chart with the x axis as a DateTimeContinuousAxis. Once the date range reaches sufficient length, the column widths do not get any smaller. Instead, they start overlapping each other. In my case, I have a about 85 points over a period of about 8 months with the axis MajorStepUnit set to Days.  You can see in the first attachment, a screenshot of the chart where the column backgrounds are blue and the borders are red.  My expectation is that the column width should shrink as more columns are added & that there should be no overlapping.  Any guidance here would be appreciated. Thanks - Mitch.


Below are the xaml and code behind for creating the attached screenshot (I can send the project if desired):



XAML:



<Window x:Class="MathNETTest.MainWindow"
        xmlns:local="clr-namespace:MathNETTest"
        Title="MainWindow" Height="750" Width="925" >
 
    <Window.Resources>
 
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MathNETTest;component/Themes/Windows8/Telerik.Windows.Controls.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MathNETTest;component/Themes/Windows8/Telerik.Windows.Controls.DataVisualization.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MathNETTest;component/Themes/Windows8/Telerik.Windows.Controls.Chart.xaml"/>
            </ResourceDictionary.MergedDictionaries>
 
            <Style TargetType="{x:Type telerik:BarSeries}" BasedOn="{StaticResource BarSeriesStyle}">
                <Setter Property="PointTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Border Background="Blue" BorderBrush="Red" BorderThickness="1">                               
                            </Border>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>              
            </Style>
        </ResourceDictionary>
    </Window.Resources>
 
    <Grid>                     
        <telerik:RadCartesianChart x:Name="MyChart">
             
            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:DateTimeContinuousAxis LabelFitMode="Rotate"/>
 
            </telerik:RadCartesianChart.HorizontalAxis>
             
            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis/>
            </telerik:RadCartesianChart.VerticalAxis>
 
            <telerik:RadCartesianChart.Grid>
                <telerik:CartesianChartGrid MajorLinesVisibility="XY">
 
                    <telerik:CartesianChartGrid.MajorXLineStyle>
                        <Style TargetType="Line">
                            <Setter Property="Stroke" Value="Black"/>                              
                        </Style>
                    </telerik:CartesianChartGrid.MajorXLineStyle>
 
                    <telerik:CartesianChartGrid.MajorYLineStyle>
                        <Style TargetType="Line">
                            <Setter Property="Stroke" Value="Black"/>                           
                        </Style>
                    </telerik:CartesianChartGrid.MajorYLineStyle>
 
                </telerik:CartesianChartGrid>
            </telerik:RadCartesianChart.Grid>
 
        </telerik:RadCartesianChart>
    </Grid>
</Window>




Code behind:



using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
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 System.ComponentModel;
using System.Numerics;
using Telerik.Windows.Controls.ChartView;
 
namespace MathNETTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<MySeries> Series { get; set; } 
        public ChartSeriesProvider SeriesProvider { get; set; }
 
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
 
            ObservableCollection<MyPoint> points = new ObservableCollection<MyPoint>();
            MyPoint p = new MyPoint(new DateTime(2012, 9, 2), 4); points.Add(p);
            p = new MyPoint(new DateTime(2012, 9, 3), 6); points.Add(p);
            p = new MyPoint(new DateTime(2012, 9, 4), 4); points.Add(p);
            p = new MyPoint(new DateTime(2012, 9, 5), 3); points.Add(p);
            p = new MyPoint(new DateTime(2012, 9, 6), 1); points.Add(p);
            p = new MyPoint(new DateTime(2012, 9, 30), 3); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 1), 1); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 2), 2); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 3), 3); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 4), 1); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 28), 4); points.Add(p);
            p = new MyPoint(new DateTime(2012, 10, 29), 2); points.Add(p);
            p = new MyPoint(new DateTime(2012, 11, 25), 2); points.Add(p);
            p = new MyPoint(new DateTime(2012, 12, 30), 5); points.Add(p);
            p = new MyPoint(new DateTime(2012, 12, 31), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 1), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 2), 3); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 3), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 7), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 8), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 9), 3); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 10), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 13), 3); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 14), 14); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 15), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 16), 9); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 17), 5); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 20), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 21), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 22), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 23), 8); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 24), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 28), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 29), 20); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 30), 17); points.Add(p);
            p = new MyPoint(new DateTime(2013, 1, 31), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 3), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 4), 15); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 5), 7); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 6), 10); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 7), 10); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 8), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 11), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 12), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 13), 9); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 14), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 17), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 18), 9); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 19), 5); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 20), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 21), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 22), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 24), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 25), 11); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 26), 7); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 27), 8); points.Add(p);
            p = new MyPoint(new DateTime(2013, 2, 28), 8); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 1), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 3), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 4), 13); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 5), 11); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 6), 10); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 7), 11); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 8), 5); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 10), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 11), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 12), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 13), 6); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 14), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 15), 11); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 16), 10); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 17), 8); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 18), 5); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 19), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 20), 7); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 21), 3); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 23), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 25), 4); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 26), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 27), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 3, 28), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 4, 9), 2); points.Add(p);
            p = new MyPoint(new DateTime(2013, 4, 18), 1); points.Add(p);
            p = new MyPoint(new DateTime(2013, 5, 20), 1); points.Add(p);
 
            this.Series = new ObservableCollection<MySeries>();
            MySeries series = new MySeries();
            series.Points = points;
            this.Series.Add(series);
 
            this.SeriesProvider = new ChartSeriesProvider();
            this.SeriesProvider.Source = this.Series;
 
            CategoricalSeriesDescriptor sd = new CategoricalSeriesDescriptor();
            sd.CategoryPath = "X";
            sd.ValuePath = "Y";
            sd.ItemsSourcePath = "Points";
            sd.CollectionIndex = 0;
            sd.TypePath = "TelerikSeriesType";
 
            this.SeriesProvider.SeriesDescriptors.Add(sd);
 
            this.MyChart.SeriesProvider = this.SeriesProvider;
        }
    }
 
    public class MySeries
    {
        public MySeries()
        {
            this.TelerikSeriesType = typeof(BarSeries);
        }
        public SolidColorBrush Color { get; set; }
        public ObservableCollection<MyPoint> Points { get; set; }
 
        public Type TelerikSeriesType{get; set;}
    }
 
    public class MyPoint
    {
        public MyPoint(DateTime x, double y)
        {
            X = x;
            Y = y;
        }
 
        public DateTime X { get; set; }
        public double Y { get; set; }
    }
}




5 Answers, 1 is accepted

Sort by
0
Yavor
Telerik team
answered on 15 Jan 2014, 09:49 AM
Hello Mitchell,

The DateTimeContinuous axis is a continuous axis, which works very similar to a linear axis. This means that it creates the slots for your items based on the date time range and some major step, which can be calculated automatically or specified manually. Be default if the major step is not specified, the axis will try to come up with a step that will allow your axis to show a reasonable amount of major ticks (and labels). But in your scenario you are using bars and you have some clustered data points - some are close together, others are some distance away. In this scenario it is best if you choose the granularity of the axis yourself. If you know that the granularity for your data is day, you can adjust the slots for your bars by specifying the MajorStep and MajorStepUnit like this:

<telerik:DateTimeContinuousAxis MajorStep="1" MajorStepUnit="Day" />

It is important to choose the correct major step and major step unit for your scenario. Too fine grained and you will end up having too thin bars and lots of labels and ticks. Too coarse grained and your bars will start to overlap. So choosing the correct ones depends on your data.

If you end up having more labels than you want there are several way in which you can reduce them:
1) First you can try setting LabelInterval, which defines the step at which labels are positioned;
2) Another option is to use shorter format, which is defined in LabelFormat property;
3) Also it is possible to rotate the labels a bit so that they don't overlap. This is done via the combination of these 2 properties: LabelFitMode="Rotate" LabelRotationAngle="{angle}";
4) Yet another option could be to place the labels on multiple rows. This can be set with this property: LabelFitMode="MultiLine";

All these properties control only the labels of your axis. The ticks will not be changed in any way and your bars will be displayed properly. So my advice is to configure the axis to show your bars correctly using the MajorStepUnit and MajorStep properties, then use one or several of the approaches described above to reduce the number of labels in your axis.

Regards,
Yavor
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
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 >>
0
Mitchell
Top achievements
Rank 1
answered on 15 Jan 2014, 07:35 PM
I've "solved" my issue using Reflection on the cartesian grid.  So, certainly not a recommended way of doing things since any version upgrade could invalidate this method. However, for academic purposes, here's what can be done to make gridlines without an associated label transparent:

private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            SolidColorBrush transparentBrush = new SolidColorBrush(Colors.Transparent);
 
            //Do some funky reflection to hide tick marks that don't have a label
            FieldInfo majorXLinesFieldInfo = this.MyGrid.GetType().GetField("majorXLines", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance);
            if (null != majorXLinesFieldInfo)
            {
                //GridLinesInfo is a private class
                var majorXLines = majorXLinesFieldInfo.GetValue(this.MyGrid);
 
                FieldInfo linePresentersInfo = majorXLines.GetType().GetField("LinePresenters");
                FieldInfo linesInfo = majorXLines.GetType().GetField("Lines");
                if (null != linePresentersInfo && null != linesInfo)
                {
                    var linePresenters = linePresentersInfo.GetValue(majorXLines);
                    var lines = linesInfo.GetValue(majorXLines);
                    int i = 0;
                    foreach (var line in (IEnumerable)linePresenters)
                    {
                        var gridLine = ((IList)lines)[i];
 
                        FieldInfo associatedTickFieldInfo = gridLine.GetType().GetField("AssociatedTick");
                        if (null != associatedTickFieldInfo)
                        {
                            var associatedTick = associatedTickFieldInfo.GetValue(gridLine);
 
                            FieldInfo associatedLabelInfo = associatedTick.GetType().GetField("associatedLabel", BindingFlags.Instance | BindingFlags.NonPublic);
                            if (null != associatedLabelInfo)
                            {
                                var associatedLabel = associatedLabelInfo.GetValue(associatedTick);
                                if (null == associatedLabel)
                                {
                                     
                                    ((Line)line).Stroke = transparentBrush;
                                    ((Line)line).Fill = transparentBrush;
 
                                }                              
                            }
                        }
 
                        i++;
                    }
                }              
            }
        }
0
Yavor
Telerik team
answered on 20 Jan 2014, 01:31 PM
Hi Mitchell,

So your problem is how to hide the grid lines that don't have an associated label, is it? I didn't understand that from your initial post.

Regards,
Yavor
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
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 >>
0
Mitchell
Top achievements
Rank 1
answered on 20 Jan 2014, 04:10 PM
That's basically it. I wanted a fairly small number of grid lines (all with labels). 5-10 depending on the width of the chart. I could achieve that by setting the major tick step, but that resulted in the overlapping columns because the column width grew with those settings. I needed the columns to stay the width of "1 day".
0
Accepted
Yavor
Telerik team
answered on 21 Jan 2014, 08:45 AM
Hello Mitchell,

I can confirm we have identified this limitation of the chartview grid and will look into it. A better approach for your scenario would be to use custom grid line annotations instead. This way you can display grid lines exactly where you need them. Documentation of annotations can be found here.

Regards,
Yavor
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
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 >>
Tags
ChartView
Asked by
Mitchell
Top achievements
Rank 1
Answers by
Yavor
Telerik team
Mitchell
Top achievements
Rank 1
Share this question
or