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

DateTimeContinuousAxis Ticks

12 Answers 590 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Marcello
Top achievements
Rank 1
Iron
Marcello asked on 06 Jun 2013, 11:06 AM
Hi,

The scenario: a zoommable chart with a DateTime axys that contains a lot of points, approxymately one each 5 or 6 minutes for years.

I set the X Axys MaximumTicks property to 10 and all work good.

But:

1) If I'm looking a range of years the time is not interesting for me
2)  If I'm looking a range of years I prefer that any ticks go exaclty to one day (1/3/2013 00:00:00 instead of 1/3/2013 12:23:45)
3)  If I'm looking a range of hours the time is really important

How to menage manually the parameters 
MajorStepUnit and MajorStep?
The ActualRangeChanged event don't exists!

Thank's
marc.








12 Answers, 1 is accepted

Sort by
0
Rosko
Telerik team
answered on 11 Jun 2013, 10:26 AM
Hi Marcello,

For the time being, there is no good way to do this. But, with the release of Q2, which will be released by the end of the business week, there will be an easy way to do that. The new property, ActualVisibleRange, and the new event ZoomChanged will be introduced. And you would need to do something like the following:
private void chart_ZoomChanged(object sender, Telerik.Windows.Controls.ChartView.ChartZoomChangedEventArgs e)
        {
            var axis = (chart.HorizontalAxis as DateTimeContinuousAxis);
            var range = axis.ActualVisibleRange.Maximum - axis.ActualVisibleRange.Minimum;
            if (range > TimeSpan.FromDays(365))
            {
                axis.LabelFormat = "dd-MMM-yyyy";
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Day;
            }
            else
            {
                axis.LabelFormat = "dd-MMM-yyyy HH:mm";
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
            }
        }

Regards, Rosko
Telerik

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Marcello
Top achievements
Rank 1
Iron
answered on 17 Jun 2013, 10:22 AM
Hi Rosko,

Thank's very much.
With new version is possible to obtain good results.

But in certain case the dll fails.

Look the attatched example.I set allways the Major Step Unit as Day and Major Step as a int number.
Execute the example, maximize it and start to reduce zoom bar from left to right.
At certain point the chart show point at 06:00 hours!

thank's,
marc.

<telerik:RadCartesianChart ZoomChanged="chart_ZoomChanged">
           <telerik:RadCartesianChart.HorizontalAxis>
               <telerik:DateTimeContinuousAxis MajorStepUnit="Day" MajorStep="2" Name="mX"/>
           </telerik:RadCartesianChart.HorizontalAxis>
           <telerik:RadCartesianChart.VerticalAxis>
               <telerik:LinearAxis/>
           </telerik:RadCartesianChart.VerticalAxis>
           <telerik:LineSeries Name="mS">
 
           </telerik:LineSeries>
           <telerik:RadCartesianChart.Behaviors>
               
               <telerik:ChartPanAndZoomBehavior/>
           </telerik:RadCartesianChart.Behaviors>
       </telerik:RadCartesianChart>

public MainWindow()
        {
            InitializeComponent();
 
            for (int i = 0; i < 100;i++ )
                mS.DataPoints.Add(new Telerik.Charting.CategoricalDataPoint() { Category = System.DateTime.Today.AddHours(i*6), Value = 5 });
             
        }
        private void chart_ZoomChanged(object sender, Telerik.Windows.Controls.ChartView.ChartZoomChangedEventArgs e)
        {
 
            var axis = mX;
            var range = axis.ActualVisibleRange.Maximum - axis.ActualVisibleRange.Minimum;
 
            double lbs = System.Math.Ceiling(range.TotalDays / 10);
 
            if (lbs > 0 && range.TotalDays / lbs > 5)
            {
                //axis.PlotMode = Telerik.Charting.AxisPlotMode.BetweenTicks;
                //axis.GapLength = 1;
                axis.LabelFormat = "yyyy/MM/dd\r\nHH:mm:ss";
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Day;
 
                axis.MajorStep = lbs;
 
                //axis.LabelInterval = 1;
 
               
 
                return;
            }
 
        }
0
Rosko
Telerik team
answered on 20 Jun 2013, 07:50 AM
Hello Marcello,

Thank you for the provided code, it proved useful for understanding the scenario.

What you are experiencing is a completely expected behavior. The chart respects this property until some level of zoom in. It has some internal heuristics which make sure that there are a certain number of ticks on the axis. Otherwise, the chart will not make much sense if it has very few ticks on its axis. This is why it changes the MajorStepUnit as it zooms in to half a day and then to one third of a day. In the end, at one moment, you will have one point/tick in the visible range.

Regards,
Rosko
Telerik

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Marcello
Top achievements
Rank 1
Iron
answered on 20 Jun 2013, 09:15 AM
Hi Rosko,

Sorry, but I think this is a bug.
I rewrited my example.
Please run it and maximize the form.
Move zoom bar from left to right. When the zoom bar size is about half of form width the labels for 12:00 hours appears also if the 

chart_ZoomChanged method is granting that 11 labels is visibles (llok the new txtbox on bottom left corner).

Now stop project. Change the mMaxLabelsCount value to 30 and restart it. In the same situasion now the program grant to show 24/25 labels but anyway the new labels appears overlapping others!

marc.

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <telerik:RadCartesianChart ZoomChanged="chart_ZoomChanged">
            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:DateTimeContinuousAxis MajorStepUnit="Day" MajorStep="2" Name="mX"/>
            </telerik:RadCartesianChart.HorizontalAxis>
            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis/>
            </telerik:RadCartesianChart.VerticalAxis>
            <telerik:LineSeries Name="mS">
 
            </telerik:LineSeries>
            <telerik:RadCartesianChart.Behaviors>
                
                <telerik:ChartPanAndZoomBehavior/>
            </telerik:RadCartesianChart.Behaviors>
        </telerik:RadCartesianChart>
 
        <TextBlock Name="mInfo" Grid.Row="1"/>
    </Grid>

private const int mMaxLabelsCount = 15;
 
        public MainWindow()
        {
            InitializeComponent();
 
            for (int i = 0; i < 100;i++ )
                mS.DataPoints.Add(new Telerik.Charting.CategoricalDataPoint() { Category = System.DateTime.Today.AddHours(i*6), Value = 5 });
 
            Loaded += (x, y) => { chart_ZoomChanged(null, null); };
        }
 
        private void chart_ZoomChanged(object sender, Telerik.Windows.Controls.ChartView.ChartZoomChangedEventArgs e)
        {
 
            if (mX == null) return;
            if (!(mX is Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis)) return;
            var axis = (mX as Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis);
            var range = axis.ActualVisibleRange.Maximum - axis.ActualVisibleRange.Minimum;
            bool ms = false;
            double k;
 
            if (range.TotalHours > 12 * mMaxLabelsCount) //> 120 ore
            {
                k = range.TotalDays;
                var lbs = System.Math.Ceiling(k / mMaxLabelsCount);
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Day;
                axis.MajorStep = lbs;
            }
            else if (range.TotalHours > 6 * mMaxLabelsCount) //>60
            {
                k = range.TotalHours;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                axis.MajorStep = 12;
            }
            else if (range.TotalHours > 3 * mMaxLabelsCount)
            {
                k = range.TotalHours;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                axis.MajorStep = 6;
            }
            else if (range.TotalHours > mMaxLabelsCount)
            {
                k = range.TotalHours;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                axis.MajorStep = 3;
            }
            else if (range.TotalMinutes > 30 * mMaxLabelsCount)
            {
                k = range.TotalHours;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                axis.MajorStep = 1;
            }
            else if (range.TotalMinutes > 15 * mMaxLabelsCount)
            {
                k = range.TotalMinutes;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Minute;
                axis.MajorStep = 30;
            }
            else if (range.TotalMinutes > mMaxLabelsCount)
            {
                k = range.TotalMinutes;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Minute;
                axis.MajorStep = 15;
            }
            else if (range.TotalSeconds > 30 * mMaxLabelsCount)
            {
                k = range.TotalMinutes;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Minute;
                axis.MajorStep = 1;
            }
            else if (range.TotalSeconds > 15 * mMaxLabelsCount)
            {
                k = range.TotalSeconds;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
                axis.MajorStep = 30;
            }
            else if (range.TotalSeconds > 1 * mMaxLabelsCount)
            {
                k = range.TotalSeconds;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
                axis.MajorStep = 15;
            }
            else if (range.TotalMilliseconds > 100 * mMaxLabelsCount)
            {
                k = range.TotalSeconds;
                axis.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
                axis.MajorStep = 1;
            }
            else
            {
                k = 0;
                axis.MajorStep = 0;
                ms = true;
            }
 
            axis.LabelFormat = "yyyy/MM/dd\r\nHH:mm:ss" + (ms ? ".xxx" : string.Empty);
 
 
            if (axis.MajorStep > 0 && k > 0)
                mInfo.Text = "Granted Labels>=" + System.Math.Floor( k / axis.MajorStep).ToString();
            else
                mInfo.Text = "Granted Labels:?";
 
            mInfo.Text += " " + axis.MajorStepUnit.ToString() + " " + axis.MajorStep.ToString();
 
        }

0
Rosko
Telerik team
answered on 25 Jun 2013, 07:12 AM
Hi Marc,

Thank you for the code and detailed instructions!

I suspect that there is some miscommunication. If this post still does not solve all issues. Can you please share a sketch what you are referring as a bug by pointing or highlighting in the picture?
I used them and you can see the result that I get in the two attached pictures.

I hope that you already understood that the chart is changing the MajorStepUnit by itself as it zooms in and this cannot be changed. Sorry if it is causing any inconvenience. 

If you are regarding the overlapping labels as a bug, that can be fixed in more than one way. You can take advantage of the following properties. I believe the first two speak of themselves. The last one sets how many labels should be there per number of ticks. For instance, if you set the property to 2, this means you will have one label for every two ticks and etc. Last but not least, you can reduce the number of ticks, which I believe you already know how to do.
axis.LabelFitMode
axis.LabelRotationAngle
axis.LabelInterval

I hope this has cleared the miscommunication, if not please provide an image showing what do you refer as a bug.

Regards,
Rosko
Telerik

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Marcello
Top achievements
Rank 1
Iron
answered on 08 Jul 2013, 11:12 AM
Hi Rosko,

My problem is simply: how to obtain a good chart visual experience in charts with a lot of datapoints (Years of seconds intervals data)?
Please ignore all previous posts and we try to restart from here.

I create a new simple example:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <telerik:RadCartesianChart>
            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:DateTimeContinuousAxis MajorStepUnit="Day" MajorStep="2" Name="mX"/>
            </telerik:RadCartesianChart.HorizontalAxis>
            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis/>
            </telerik:RadCartesianChart.VerticalAxis>
            <telerik:BarSeries Name="mS">
 
            </telerik:BarSeries>
            <telerik:RadCartesianChart.Behaviors>
                
                <telerik:ChartPanAndZoomBehavior/>
            </telerik:RadCartesianChart.Behaviors>
        </telerik:RadCartesianChart>
 
        <TextBlock Name="mInfo" Grid.Row="1"/>
    </Grid>

public MainWindow()
        {
            InitializeComponent();
 
            for (int i = 0; i < 100;i++ )
                mS.DataPoints.Add(new Telerik.Charting.CategoricalDataPoint() { Category = System.DateTime.Today.AddHours(i*6), Value = 5 });
 
             
        }

How to change it to obtain:

1) No x lables overlapping for each windows size and zoom level selection
2) No Bar series overlapping
3) Good tick choose depending on zoom selection level (exact days for weeks, exact 12:00 for days, exact ours for day...) [this request is obviously less important]
4) Mantain the previous results (1,2,3) if dataset change.

Thank's 
marc.
0
Marcello
Top achievements
Rank 1
Iron
answered on 08 Jul 2013, 11:45 AM
Hi,

Perhaps I finded an acceptable solution setting one time the MajorStep on min data interval and working only with labels interval on zoom change event:

<Window.Resources>
 
        <Style x:Key="mCustomLabelStyle" TargetType="{x:Type TextBlock}">
 
            <Setter Property="TextAlignment" Value="Center"/>
            <Setter Property="FontSize" Value="10"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
 
         
         
        <telerik:RadCartesianChart ZoomChanged="RadCartesianChart_ZoomChanged" Name="mC">
            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:DateTimeContinuousAxis Name="mX"/>
            </telerik:RadCartesianChart.HorizontalAxis>
            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis/>
            </telerik:RadCartesianChart.VerticalAxis>
            <telerik:BarSeries Name="mS">
 
            </telerik:BarSeries>
            <telerik:RadCartesianChart.Behaviors>
                
                <telerik:ChartPanAndZoomBehavior/>
            </telerik:RadCartesianChart.Behaviors>
        </telerik:RadCartesianChart>
 
        <TextBlock Name="mInfo" Grid.Row="1"/>
    </Grid>

public MainWindow()
       {
           InitializeComponent();
 
           System.DateTime? dprev=null;
           System.DateTime d;
           System.TimeSpan dmin = new TimeSpan(0);
 
           for (int i = 0; i < 100; i++)
           {
               d = System.DateTime.Today.AddHours(i * 6);
 
               if (dprev.HasValue && (d - dprev.Value) > dmin) dmin = (d - dprev.Value);
               dprev = d;
 
               mS.DataPoints.Add(new Telerik.Charting.CategoricalDataPoint() { Category = d, Value = 5 });
           }
 
           mX.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
           mX.MajorStep = dmin.TotalSeconds;
           mX.LabelStyle = Resources["mCustomLabelStyle"] as Style;
 
           mC.Loaded += (x, y) => { RadCartesianChart_ZoomChanged(null, null); };
            
       }
 
       private void RadCartesianChart_ZoomChanged(object sender, Telerik.Windows.Controls.ChartView.ChartZoomChangedEventArgs e)
       {
           if (mX == null) return;
           if (!(mX is Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis)) return;
           var axis = (mX as Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis);
           var range = axis.ActualVisibleRange.Maximum - axis.ActualVisibleRange.Minimum;
 
           int t = (int)(range.TotalSeconds / mX.MajorStep);
 
           mX.LabelInterval = System.Math.Max(t / mMaxLabelsCount, 1);
 
 
           axis.LabelFormat = "yyyy/MM/dd\r\nHH:mm:ss" + ((range.TotalMilliseconds <= 100 * mMaxLabelsCount) ? ".xxx" : string.Empty);
            
       }
0
Marcello
Top achievements
Rank 1
Iron
answered on 10 Jul 2013, 07:42 AM
Hi Rosko,

a new version of solution with this strategies:

  • The X Axis Major Step Unit is set to Seconds
  • The X Axis Step is set to minimum of points distance, in seconds

This grant that the chart don't add never infra ticks

  • The X Axis Minimum is manually set to a good "exact" date, in example 1/1/2013 instead of 1/1/2013 00:00:01

This grant the tick is allways on a "exact" position instead of the point position

  • The LabelFitMode is set to multiline

This grant that a good visual experience in possible also resizing the chart.

  • In Zoom changed event I find the firts tick, the last tick, the number of visible ticks (via ActualVisibleRange)
  • I choose Label Interval and Label Offset for a good visual experience.

This work pretty good, but:

  • Is not possible to determine allways exacltly the first and last tick, probabilly for approximations (look the images T1 and T2. The second image don't show first tick but bot cases ave the identical [at milliseconds level] ActualVisibleRange.
  • This cause that in certain cases the procedure don't determine correctly the first tick and unespected "not exact" dates appears for a moment [This is visible zooming slowly, in certain cases hours appears also if the visible range is a lot of days]

The strategy introduce also other little problems:

  • Is not possible to choose ticks visible number (In possible to set a style for tick depending on tick index?)
  • The chart grid contains a lot of lines (In possible to set a style for grid line depending on lines index?)

Suggestions for the future:

  • Please add a FirstTick (Datetime) in ActualVisibleRange for a exact determination of LabelInterval
  • Please review the Grid architecture and the Bar architecture.

I really love your charts. I worked a lot with other chart developers. You have a really good class architetture that permit to work simply and linearly in a lot of case. Only X Axis interactions contains [for the moment] not good implementations:

  • The bar width is not depending on X axys tiks!! It depends only on the back and previous point positions!!
The test code after the signature.

Thank's very much,
marc

<Window.Resources>
 
        <Style x:Key="mCustomLabelStyle" TargetType="{x:Type TextBlock}">
 
            <Setter Property="TextAlignment" Value="Center"/>
            <Setter Property="FontSize" Value="10"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
 
         
         
        <telerik:RadCartesianChart ZoomChanged="RadCartesianChart_ZoomChanged" Name="mC">
            <telerik:RadCartesianChart.HorizontalAxis>
                <telerik:DateTimeContinuousAxis Name="mX"/>
            </telerik:RadCartesianChart.HorizontalAxis>
            <telerik:RadCartesianChart.VerticalAxis>
                <telerik:LinearAxis/>
            </telerik:RadCartesianChart.VerticalAxis>
            <telerik:LineSeries Name="mS">
 
            </telerik:LineSeries>
            <telerik:RadCartesianChart.Behaviors>
                
                <telerik:ChartPanAndZoomBehavior/>
            </telerik:RadCartesianChart.Behaviors>
        </telerik:RadCartesianChart>
     
        <TextBlock Name="mInfo" Grid.Row="1"/>
    </Grid>

private double TickLength=1;
        private int mMaxLabelsCount = 10;
        private System.DateTime? FirstTick;
 
        public MainWindow()
        {
            InitializeComponent();
 
            System.DateTime? dprev=null, dmin=null;
            System.DateTime d;
            System.TimeSpan rmin = new TimeSpan(0);
 
             
            for (int i = 0; i < 100; i++)
            {
                d = System.DateTime.Today.AddMinutes(3).AddHours(i * 6);
 
                if (dprev.HasValue && (d - dprev.Value) > rmin) rmin = (d - dprev.Value);
                dprev = d;
 
                if (!dmin.HasValue || dmin > d) dmin = d;
                mS.DataPoints.Add(new Telerik.Charting.CategoricalDataPoint() { Category = d, Value = 5 });
            }
 
            //If nopoints return
            if (!dmin.HasValue) return;
 
            //R Min Analysis
            if (rmin >= TimeSpan.FromDays(1)) rmin = TimeSpan.FromDays((int)(rmin.TotalDays));
            else if(rmin >= TimeSpan.FromHours(12)) rmin = TimeSpan.FromHours(12);
            else if (rmin >= TimeSpan.FromHours(8)) rmin = TimeSpan.FromHours(8);
            else if (rmin >= TimeSpan.FromHours(6)) rmin = TimeSpan.FromHours(6);
            else if (rmin >= TimeSpan.FromHours(4)) rmin = TimeSpan.FromHours(4);
            else if (rmin >= TimeSpan.FromHours(3)) rmin = TimeSpan.FromHours(3);
            else if (rmin >= TimeSpan.FromHours(2)) rmin = TimeSpan.FromHours(1);
            else if (rmin >= TimeSpan.FromHours(1)) rmin = TimeSpan.FromHours(1);
            else if (rmin >= TimeSpan.FromMinutes(30)) rmin = TimeSpan.FromMinutes(30);
            else if (rmin >= TimeSpan.FromMinutes(20)) rmin = TimeSpan.FromMinutes(20);
            else if (rmin >= TimeSpan.FromMinutes(15)) rmin = TimeSpan.FromMinutes(15);
            else if (rmin >= TimeSpan.FromMinutes(10)) rmin = TimeSpan.FromMinutes(10);
            else if (rmin >= TimeSpan.FromMinutes(5)) rmin = TimeSpan.FromMinutes(5);
            else if (rmin >= TimeSpan.FromMinutes(1)) rmin = TimeSpan.FromMinutes(1);
            else if (rmin >= TimeSpan.FromSeconds(30)) rmin = TimeSpan.FromSeconds(30);
            else if (rmin >= TimeSpan.FromSeconds(20)) rmin = TimeSpan.FromSeconds(20);
            else if (rmin >= TimeSpan.FromSeconds(15)) rmin = TimeSpan.FromSeconds(15);
            else if (rmin >= TimeSpan.FromSeconds(10)) rmin = TimeSpan.FromSeconds(10);
            else if (rmin >= TimeSpan.FromSeconds(5)) rmin = TimeSpan.FromSeconds(5);
            else if (rmin >= TimeSpan.FromSeconds(1)) rmin = TimeSpan.FromSeconds(1);
            else if (rmin >= TimeSpan.FromMilliseconds(500)) rmin = TimeSpan.FromMilliseconds(500);
            else if (rmin >= TimeSpan.FromMilliseconds(100)) rmin = TimeSpan.FromMilliseconds(100);
            else if (rmin >= TimeSpan.FromMilliseconds(50)) rmin = TimeSpan.FromMilliseconds(50);
            else if (rmin >= TimeSpan.FromMilliseconds(20)) rmin = TimeSpan.FromMilliseconds(20);
            else if (rmin >= TimeSpan.FromMilliseconds(10)) rmin = TimeSpan.FromMilliseconds(10);
            else if (rmin >= TimeSpan.FromMilliseconds(5)) rmin = TimeSpan.FromMilliseconds(5);
            else rmin = TimeSpan.FromMilliseconds(1);
 
            //D Min Analysis -- Additing a gosth point, if necessary, for a good tick start
            System.DateTime sdate = new System.DateTime(dmin.Value.Year, dmin.Value.Month, dmin.Value.Day);
            FirstTick = sdate.AddSeconds(rmin.TotalSeconds * System.Math.Floor((dmin.Value - sdate).TotalSeconds / rmin.TotalSeconds));
            if (FirstTick.Value < dmin.Value)
                mX.Minimum = FirstTick.Value;
             
            TickLength = rmin.TotalSeconds;
            mX.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
            mX.MajorStep = TickLength;
            mX.LabelFitMode = Telerik.Charting.AxisLabelFitMode.MultiLine;
            mX.PlotMode = Telerik.Charting.AxisPlotMode.OnTicks;
            mX.LabelStyle = Resources["mCustomLabelStyle"] as Style;
 
            mC.Loaded += (x, y) => { RadCartesianChart_ZoomChanged(null, null); };
             
        }
         
        private void RadCartesianChart_ZoomChanged(object sender, Telerik.Windows.Controls.ChartView.ChartZoomChangedEventArgs e)
        {
            if (mX == null) return;
            if(!FirstTick.HasValue) return;
            if (!(mX is Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis)) return;
            var axis = (mX as Telerik.Windows.Controls.ChartView.DateTimeContinuousAxis);
 
             
             
            var range = axis.ActualVisibleRange.Maximum - axis.ActualVisibleRange.Minimum;
 
            System.TimeSpan rv;
            if (range.TotalHours > 12 * mMaxLabelsCount) //> 120 ore
                rv = TimeSpan.FromDays(System.Math.Ceiling(range.TotalDays / mMaxLabelsCount));
            else if (range.TotalHours > 6 * mMaxLabelsCount) //>60
                rv=TimeSpan.FromHours(12);
            else if (range.TotalHours > 3 * mMaxLabelsCount)
                rv = TimeSpan.FromHours(6);
            else if (range.TotalHours > mMaxLabelsCount)
                rv = TimeSpan.FromHours(3);
            else if (range.TotalMinutes > 30 * mMaxLabelsCount)
                rv = TimeSpan.FromHours(1);
            else if (range.TotalMinutes > 15 * mMaxLabelsCount)
                rv = TimeSpan.FromMinutes(30);
            else if (range.TotalMinutes > mMaxLabelsCount)
                rv = TimeSpan.FromHours(15);
            else if (range.TotalSeconds > 30 * mMaxLabelsCount)
                rv = TimeSpan.FromHours(1);
            else if (range.TotalSeconds > 15 * mMaxLabelsCount)
                rv = TimeSpan.FromSeconds(30);
            else if (range.TotalSeconds > 1 * mMaxLabelsCount)
                rv = TimeSpan.FromSeconds(15);
            else if (range.TotalMilliseconds > 100 * mMaxLabelsCount)
                rv = TimeSpan.FromSeconds(1);
            else
                rv = TimeSpan.FromSeconds(TickLength);
 
            System.DateTime firsttick = FirstTick.Value.AddSeconds(TickLength * System.Math.Floor((axis.ActualVisibleRange.Minimum - FirstTick.Value).TotalSeconds / TickLength));
            System.DateTime lasttick = FirstTick.Value.AddSeconds(TickLength * System.Math.Floor((axis.ActualVisibleRange.Maximum - FirstTick.Value).TotalSeconds / TickLength));
            int ticks = (int)((lasttick - firsttick).TotalSeconds / TickLength) + 1;
 
            TimeSpan sv = rv.TotalDays >= 1 ? TimeSpan.FromDays(1) : rv;
            System.DateTime sdate = new System.DateTime(FirstTick.Value.Year, FirstTick.Value.Month, FirstTick.Value.Day);
            System.DateTime firstlabeltick = sdate.AddSeconds(sv.TotalSeconds * System.Math.Ceiling((axis.ActualVisibleRange.Minimum - sdate).TotalSeconds / sv.TotalSeconds));
            int ticklabelinterval = System.Math.Max((int)(rv.TotalSeconds / TickLength), 1);
            int firstlabeloffset = (int)((firstlabeltick - firsttick).TotalSeconds / TickLength);
 
 
            mX.LabelInterval = ticklabelinterval;
            mX.LabelOffset = firstlabeloffset;
 
            axis.LabelFormat = "yyyy/MM/dd\r\nHH:mm:ss" + ((range.TotalMilliseconds <= 100 * mMaxLabelsCount) ? ".fff" : string.Empty);
 
            mInfo.Text = "LabelInterval: " + ticklabelinterval.ToString() + "; Offset : " + firstlabeloffset.ToString() + "; Min : " + axis.ActualVisibleRange.Minimum.ToString("yyyy/MM/dd HH:mm:ss")
                    + "; First Tick : " + firsttick.ToString("yyyy/MM/dd HH:mm:ss") + "; First Label Tick : " + firstlabeltick.ToString("yyyy/MM/dd HH:mm:ss") + "; Visible Minimum: " + axis.ActualVisibleRange.Minimum.Ticks.ToString();
        }

0
Rosko
Telerik team
answered on 11 Jul 2013, 01:04 PM
Hello Marc,

I am happy to see that you reached to this solution.

I ran your code and saw the described behavior. I can confirm that it is due to the rounding of the double of seconds. Nevertheless, it delivers a really nice user experience.

There is a property called MaximumTicks, but in order to have an effect, you need to leave the MajorStepUnit and MajorStep unset, which will lead to a behavior that you are successfully avoiding by doing those settings on zoom changed.

We do not support such scenario where you can control the number of gridlines. I have added it as a feature request at our public issue tracking system. You can vote for it to raise priority and monitor its progress.

The bar width depends of the size of each category in the chart. You can control its width, but have in mind that if you have it fixed, it will not rescale whenever you resize the window/chart.
<telerik:BarSeries Name="mS">
    <telerik:BarSeries.PointTemplate>
        <DataTemplate>
            <Rectangle Fill="Blue" Width="10"/>
        </DataTemplate>
    </telerik:BarSeries.PointTemplate>
</telerik:BarSeries>


I will forward your inquiries regarding the bar and grid architecture and the first tick property to the developers' team.

Thank you for your cooperation and understanding.

Regards,
Rosko
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
Valentin
Top achievements
Rank 1
Iron
Iron
answered on 28 Apr 2017, 10:13 AM

Hello Telerik,

 

I have a similar scenario but I have a problem : I'm using a method to update the datetime axis and set MajorStep (and unit) depending on the period.

My method :

private void updateAxesDateTime(DateTimeContinuousAxis pAxe, DateTime pDateDebut, DateTime pDateFin)
        {
            TimeSpan range = pDateFin - pDateDebut;
 
            if (range >= TimeSpan.FromDays(1460)) //Visu sur 4 ans ou +
            {
                pAxe.LabelFormat = "dd-MM-yyyy";
                //Interval 1 an
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Year;
                pAxe.MajorStep = 1;
            }
            else if (range >= TimeSpan.FromDays(730) && range < TimeSpan.FromDays(1460)) //Visu sur 2 à 4 ans
            {
                pAxe.LabelFormat = "dd-MM-yyyy";
                //Interval 6 mois
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Month;
                pAxe.MajorStep = 6;
            }
            else if (range >= TimeSpan.FromDays(124) && range < TimeSpan.FromDays(730)) //Visu sur 4 mois à 2 ans
            {
                pAxe.LabelFormat = "dd-MM-yyyy";
                //Interval 1 mois
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Month;
                pAxe.MajorStep = 1;
            }
            else if (range >= TimeSpan.FromDays(31) && range < TimeSpan.FromDays(124)) //Visu sur 1 mois à 4 mois
            {
                pAxe.LabelFormat = "dd-MM";
                //Interval 1 semaine
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Week;
                pAxe.MajorStep = 1;
            }
            else if (range >= TimeSpan.FromDays(4) && range < TimeSpan.FromDays(31)) //Visu sur 4 jours à 1 mois
            {
                pAxe.LabelFormat = "dd-MM";
                //Interval 1 jour
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Day;
                pAxe.MajorStep = 1;
            }
            else if (range >= TimeSpan.FromDays(2) && range < TimeSpan.FromDays(4)) //Visu sur 2 jours à 4 jours
            {
                pAxe.LabelFormat = "dd-MM HH:mm";
                //Interval 6 heure
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                pAxe.MajorStep = 6;
            }
            else if (range >= TimeSpan.FromHours(4) && range < TimeSpan.FromDays(2)) //Visu sur 4h à 2 jours
            {
                pAxe.LabelFormat = "dd-MM HH:mm";
                //Interval 1 heure
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
                pAxe.MajorStep = 1;
                 
            }
            else if (range >= TimeSpan.FromHours(1) && range < TimeSpan.FromHours(4)) //Visu sur 1 à 4 heures
            {
                pAxe.LabelFormat = "dd-MM HH:mm";
                //Interval 30 minutes
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Minute;
                pAxe.MajorStep = 30
            }
            else if (range >= TimeSpan.FromMinutes(4) && range < TimeSpan.FromHours(1)) //Visu sur 4 minutes à 1 heure
            {
                pAxe.LabelFormat = "dd-MM HH:mm";
                //Interval 1 minute
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Minute;
                pAxe.MajorStep = 1;
            }
            else if (range >= TimeSpan.FromMinutes(1) && range < TimeSpan.FromMinutes(4)) //Visu sur 1 à 4 minutes
            {
                pAxe.LabelFormat = "dd-MM HH:mm:ss";
                //Interval 15 secondes
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
                pAxe.MajorStep = 15;
            }
            else //Visu sur - de 1 minute
            {
                pAxe.LabelFormat = "dd-MM HH:mm:ss";
                //Interval 1 seconde
                pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Second;
                pAxe.MajorStep = 1;
            }
        }

 

The problem is that based on the sixth 'if', the MajorStep isn't considered and just the MajorStepUnit acted as MajorStep. For exemple, in : [....]

//Interval 6 heure
pAxe.MajorStepUnit = Telerik.Charting.TimeInterval.Hour;
pAxe.MajorStep = 6;

[...] the datetime axis represents 1 Hour for MajorStep. If I set Week for the MajorStepUnit, my datetime axis will represents 1 week.

 

At the first five,they working find, but after, there is a problem.

 

Do you have any idea ?

 

Thank you very much !

0
Petar Mladenov
Telerik team
answered on 03 May 2017, 08:41 AM
Hi Valentin,

Please find attached an isolated project and snapshot from it. Basically the project tries to simulate your scenario - DateTimeContinuousAxis with the following setup :

LabelFormat="dd-MM HH:mm"
MajorStepUnit="Hour"
MajorStep="6"

I added 24 consecutive data objects which differ by one hour.  The result is expected - 4 labels.

I hope this project can be used as a base for our discussion. We hope you will be able to modify it and show the issue you experience on your side. Thank you in advance for your cooperation.

Regards,
Petar Mladenov
Telerik by Progress
Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
0
Valentin
Top achievements
Rank 1
Iron
Iron
answered on 09 May 2017, 08:06 AM

Hello Petar,

I did the correct code but my IsStepRecalculationOnZoomEnabled property was setted to True, and the calculating tick was automatic.

I set the property to False and now, the ticks are corrects.

 

Thank you for your help !

Tags
Chart
Asked by
Marcello
Top achievements
Rank 1
Iron
Answers by
Rosko
Telerik team
Marcello
Top achievements
Rank 1
Iron
Valentin
Top achievements
Rank 1
Iron
Iron
Petar Mladenov
Telerik team
Share this question
or