2

I need to draw a chart with a series of values that extend over time. The time period between values is irregular (a few seconds). For this I am using the library LiveChart.Wpf, following Date Time tutorial and date axis example from GitHub (DateAxisExample.xaml and DateAxisExample.xaml.cs).

This is XAML:

<UserControl x:Class="Wpf.Charts.SensorChart"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <lvc:CartesianChart Series="{Binding SeriesCollection}" LegendLocation="Left">
            <lvc:CartesianChart.AxisX>
                <lvc:DateAxis Title="Time"
                              InitialDateTime="{Binding InitialDateTime}"
                              Period="{Binding Period}"
                              SelectedWindow="{Binding SelectedWindow}"
                              LabelFormatter="{Binding Formatter}">
                </lvc:DateAxis>
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

And this my code behind:

using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Helpers;
using LiveCharts.Wpf;
using System;
using System.Windows.Controls;

namespace Wpf.Charts
{
    public partial class SensorChart : UserControl
    {
        public SeriesCollection SeriesCollection { get; set; }
        public DateTime InitialDateTime { get; set; }
        public PeriodUnits Period { get; set; }
        public IAxisWindow SelectedWindow { get; set; }
        private Func<double, string> Formatter { get; set; }

        public SensorChart()
        {
            InitializeComponent();
            this.SetChartModelValues();
            this.DataContext = this;
        }

        private void SetChartModelValues()
        {
            var dayConfig = Mappers.Xy<ChartModel>()
                   .X(dayModel => (double)dayModel.DateTime.Ticks / TimeSpan.FromSeconds(1).Ticks)
                   .Y(dayModel => dayModel.Value);

            DateTime now = DateTime.Now;
            now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);

            this.SeriesCollection = new SeriesCollection(dayConfig)
            {
                new LineSeries()
                {
                    Values = new ChartValues<ChartModel>()
                    {
                        new ChartModel(now.AddSeconds(5), 3),
                        new ChartModel(now.AddSeconds(10), 6),
                        new ChartModel(now.AddSeconds(15), 8),
                        new ChartModel(now.AddSeconds(20), 4),
                        new ChartModel(now.AddSeconds(55), 7),
                        new ChartModel(now.AddSeconds(60), 2),
                        new ChartModel(now.AddSeconds(65), 6),
                        new ChartModel(now.AddSeconds(70), 8),
                        new ChartModel(now.AddSeconds(75), 4),
                        new ChartModel(now.AddSeconds(80), 7),
                        new ChartModel(now.AddSeconds(105), 3),
                        new ChartModel(now.AddSeconds(110), 6),
                        new ChartModel(now.AddSeconds(115), 8),
                        new ChartModel(now.AddSeconds(120), 4),
                        new ChartModel(now.AddSeconds(155), 7),
                        new ChartModel(now.AddSeconds(160), 2),
                        new ChartModel(now.AddSeconds(165), 6),
                        new ChartModel(now.AddSeconds(170), 8),
                        new ChartModel(now.AddSeconds(175), 4),
                        new ChartModel(now.AddSeconds(180), 7),
                    }
                }
            };
            //foreach ()

            this.InitialDateTime = now;
            this.Period = PeriodUnits.Seconds;
            this.SelectedWindow = new DateAxisWindows.FifteenSecondsAxisWindow();
            this.Formatter = this.DateLabelFormater;
        }

        private string DateLabelFormater(double value)
        {
            DateTime dateTime = new DateTime((long)(value * TimeSpan.FromSeconds(1).Ticks));
            return dateTime.ToString("HH:mm:ss");
        }
    }

    public class ChartModel
    {
        public DateTime DateTime { get; set; }
        public double Value { get; set; }

        public ChartModel(DateTime dateTime, double value)
        {
            this.DateTime = dateTime;
            this.Value = value;
        }
    }
}

But when I run the application it displays dates of the year 4036. Do you know what is happening?

Jon
  • 891
  • 13
  • 32

1 Answers1

4

Try this if you want to display the actual values:

public partial class SensorChart : UserControl
{
    public SeriesCollection SeriesCollection { get; set; }
    public DateTime InitialDateTime { get; set; }
    public Func<double, string> Formatter { get; set; }

    public SensorChart()
    {
        InitializeComponent();
        this.SetChartModelValues();
        this.DataContext = this;
    }

    private void SetChartModelValues()
    {
        var dayConfig = Mappers.Xy<ChartModel>()
                           .X(dayModel => dayModel.DateTime.Ticks)
                           .Y(dayModel => dayModel.Value);


        DateTime now = DateTime.Now;

        this.SeriesCollection = new SeriesCollection(dayConfig)
        {
            new LineSeries()
            {
                Values = new ChartValues<ChartModel>()
                {
                    new ChartModel(now.AddSeconds(5), 3),
                    new ChartModel(now.AddSeconds(10), 6),
                    new ChartModel(now.AddSeconds(15), 8),
                    new ChartModel(now.AddSeconds(20), 4),
                    new ChartModel(now.AddSeconds(55), 7),
                    new ChartModel(now.AddSeconds(60), 2),
                    new ChartModel(now.AddSeconds(65), 6),
                    new ChartModel(now.AddSeconds(70), 8),
                    new ChartModel(now.AddSeconds(75), 4),
                    new ChartModel(now.AddSeconds(80), 7),
                    new ChartModel(now.AddSeconds(105), 3),
                    new ChartModel(now.AddSeconds(110), 6),
                    new ChartModel(now.AddSeconds(115), 8),
                    new ChartModel(now.AddSeconds(120), 4),
                    new ChartModel(now.AddSeconds(155), 7),
                    new ChartModel(now.AddSeconds(160), 2),
                    new ChartModel(now.AddSeconds(165), 6),
                    new ChartModel(now.AddSeconds(170), 8),
                    new ChartModel(now.AddSeconds(175), 4),
                    new ChartModel(now.AddSeconds(180), 7),
                }
            }
        };

        this.InitialDateTime = now;
        this.Formatter = value => new DateTime((long)value).ToString("yyyy-MM:dd HH:mm:ss");
    }
}

XAML:

<lvc:CartesianChart Series="{Binding SeriesCollection}" LegendLocation="Left">
    <lvc:CartesianChart.AxisX>
        <lvc:Axis LabelFormatter="{Binding Formatter}"
                  MinValue="{Binding InitialDateTime.Ticks}">
        </lvc:Axis>
    </lvc:CartesianChart.AxisX>
</lvc:CartesianChart>

enter image description here

mm8
  • 163,881
  • 10
  • 57
  • 88
  • Thank you for your answer. I don't know why, but if I copy and paste your XAML and C# code, the chart displays the date Ticks value. I mean, I see a number like this: **6.36421203383936E+17**. It seems that the LabelFormatter is not properly set. But instead of using a binding, if I set the formatter directly in code behind, it works fine. `` and `this.axisX.LabelFormatter = value => new DateTime((long)value).ToString("yyyy-MM:dd HH:mm:ss");` Do you know why it can be? – Jon Sep 27 '17 at 13:17
  • 1
    Make sure that the Formatter property is public. In your sample code, it is private. – mm8 Sep 27 '17 at 13:20
  • Oh! It's my fault... Thank you again! – Jon Sep 27 '17 at 13:39