DateTimeContinuousAxis Ticks

10 posts, 0 answers
  1. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 06 Jun 2013 Link to this post

    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.








  2. Rosko
    Admin
    Rosko avatar
    137 posts

    Posted 11 Jun 2013 Link to this post

    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.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 17 Jun 2013 Link to this post

    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;
                }
     
            }
  5. Rosko
    Admin
    Rosko avatar
    137 posts

    Posted 20 Jun 2013 Link to this post

    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.

  6. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 20 Jun 2013 Link to this post

    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();
     
            }

  7. Rosko
    Admin
    Rosko avatar
    137 posts

    Posted 25 Jun 2013 Link to this post

    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.

  8. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 08 Jul 2013 Link to this post

    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.
  9. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 08 Jul 2013 Link to this post

    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);
                
           }
  10. Marcello
    Marcello avatar
    58 posts
    Member since:
    Apr 2013

    Posted 10 Jul 2013 Link to this post

    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();
            }

  11. Rosko
    Admin
    Rosko avatar
    137 posts

    Posted 11 Jul 2013 Link to this post

    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 >>
Back to Top
UI for WPF is Visual Studio 2017 Ready