问题
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?
回答1:
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>
来源:https://stackoverflow.com/questions/46427721/using-cartesianchart-with-dateaxis-and-datemodel-in-x-axis