在实时图表中将多个 Y 轴与日期时间的一个 X 轴绘制



在我的应用程序中,我有四个系列想要绘制成折线图。每个系列的大小相同,其中三个是double的,最后一个是DateTime列表。三个双精度系列包含在类型为 GraphData 的类对象列表中,如下所示:

public class GraphData
{
    public string Name { get; set; }
    public List<double> Data { get; set; }
}

作为附加要求,我希望为每个轴配备自己的 Y 轴。

这是我到目前为止的整个程序,它毫无问题地在自己的轴上绘制了三个图形。

public partial class MainWindow : Window
{
    public SeriesCollection SeriesCollection { get; set; }
    public AxesCollection YAxesCollection { get; set; }
    public List<GraphData> GraphDatas { get; set; }
    public List<DateTime> TimeStamps { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        GraphDatas = GetGraphData();
        TimeStamps = GetTimeStamps(GraphDatas[0].Data.Count);
        Plot();
    }
    private void Plot()
    {
        SeriesCollection = new SeriesCollection();
        YAxesCollection = new AxesCollection();
        var count = 0;
        foreach (var data in GraphDatas)
        {
            var gLineSeries = new GLineSeries
            {
                Title = data.Name,
                Values = data.Data.AsGearedValues().WithQuality(Quality.Low),
                PointGeometry = null,
                Fill = Brushes.Transparent,
                ScalesYAt = count
            };
            SeriesCollection.Add(gLineSeries);
            YAxesCollection.Add(new Axis() { Title = data.Name });
            count++;
        }
        DataContext = this;
    }
    private List<GraphData> GetGraphData()
    {
        var dataList = new List<GraphData>
        {
            new GraphData() { Name = "DataA", Data = new List<double>() { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 11.0, 11.0, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, 1.1, } },
            new GraphData() { Name = "DataB", Data = new List<double>() { 26, 33, 65, 28, 34, 55, 25, 44, 50, 36, 26, 37, 43, 62, 35, 38, 45, 32, 28, 34 } },
            new GraphData() { Name = "DataC", Data = new List<double>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 } }
        };
        return dataList;
    }
    private List<DateTime> GetTimeStamps(int limit)
    {
        var timeStamps = new List<DateTime>();
        var now = DateTime.Now;
        for (int i = 0; i < limit; i++)
        {
            if (i == 0)
                timeStamps.Add(now);
            else
            {
                now = now.AddDays(1);
                timeStamps.Add(now);
            }
        }
        return timeStamps;
    }
}

我的XAML看起来很简单:

<Grid>
    <lvc:CartesianChart Series="{Binding SeriesCollection}" 
                        AxisY="{Binding YAxesCollection}"
                        DisableAnimations="True"
                        LegendLocation="Right">
    </lvc:CartesianChart>
</Grid>

GetGraphData()GetTimeStamps()是模拟我原始函数的虚拟函数。

现在这工作正常,除了 X 轴不DateTime,因为显然我没有这么绘制它。但是我该怎么做呢?

官方文档以及此SO帖子仅显示了如何仅使用一个Y-Axis执行此操作。

我会从对模型进行一些更改开始,以便它显示全貌。时间戳是数据点的一部分,您需要将它们包装在一起,以允许实时图表mapper绘制数据。

public class DataPoint
{
    public DataPoint(DateTime timeStamp, double value)
    {
        TimeStamp = timeStamp;
        Value = value;
    }
    public double Value { get; }
    public DateTime TimeStamp { get; }
}
public class GraphData
{
    public string Name { get; set; }
    public List<DataPoint> Data { get; set; }
}

如果要保留当前的提取流 (CSV(,只需将数据 LINQ Zip为其可绘制形式即可。

public partial class MainWindow : Window
{
    public SeriesCollection SeriesCollection { get; set; }
    public Func<double, string> Formatter { get; set; }
    public AxesCollection YAxesCollection { get; set; }
    public List<GraphData> GraphDatas { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        var timeStamps = GetTimeStamps(20);
        GraphDatas = GetGraphData(timeStamps);
        Plot();
    }
    private List<GraphData> GetGraphData(List<DateTime> timeStamps)
    {
        var valuesA = new List<double>() { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 11.0, 11.0, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, 1.1, };
        var valuesB = new List<double>() { 26, 33, 65, 28, 34, 55, 25, 44, 50, 36, 26, 37, 43, 62, 35, 38, 45, 32, 28, 34 };
        var valuesC = new List<double>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
        List<DataPoint> MergeData(List<double> values) => timeStamps.Zip(values, (x, y) => new DataPoint(x, y)).ToList();
        var dataList = new List<GraphData>
        {
            new GraphData() { Name = "DataA", Data = MergeData(valuesA) },
            new GraphData() { Name = "DataB", Data = MergeData(valuesB) },
            new GraphData() { Name = "DataC", Data = MergeData(valuesC) },
        };
        return dataList;
    }
    private void Plot()
    {
        var mapper = Mappers.Xy<DataPoint>()
           .X(dp => (double)dp.TimeStamp.Ticks)
           .Y(dp => dp.Value);
        SeriesCollection = new SeriesCollection(mapper);
        YAxesCollection = new AxesCollection();
        var count = 0;
        foreach (var data in GraphDatas)
        {
            var gLineSeries = new GLineSeries
            {
                Title = data.Name,
                Values = data.Data.AsGearedValues().WithQuality(Quality.Low),
                PointGeometry = null,
                Fill = Brushes.Transparent,
                ScalesYAt = count
            };
            SeriesCollection.Add(gLineSeries);
            YAxesCollection.Add(new Axis() { Title = data.Name });
            count++;
        }
        Formatter = value => new DateTime((long)value).ToString("yyyy-MM:dd HH:mm:ss");
        DataContext = this;
    }
    private List<DateTime> GetTimeStamps(int limit)
    {
        var timeStamps = new List<DateTime>();
        var now = DateTime.Now;
        for (int i = 0; i < limit; i++)
        {
            if (i == 0)
                timeStamps.Add(now);
            else
            {
                now = now.AddDays(1);
                timeStamps.Add(now);
            }
        }
        return timeStamps;
    }
}

XAML

<lvc:CartesianChart Series="{Binding SeriesCollection}" 
                    AxisY="{Binding YAxesCollection}"
                    DisableAnimations="True"
                    LegendLocation="Right">
    <lvc:CartesianChart.AxisX>
        <lvc:Axis LabelFormatter="{Binding Formatter}" />
    </lvc:CartesianChart.AxisX>
</lvc:CartesianChart>

相关内容

  • 没有找到相关文章