c# - 在 LiveCharts 中针对 DateTime 的一个 X 轴绘制多个 Y 轴

标签 c# graph livecharts

在我的应用程序中,我有四个系列要绘制成折线图。每个系列的大小相同,其中三个是 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 因为显然我没有这样绘制它。但是我该怎么做呢?

The official documentation以及this SO Post仅显示如何仅使用一个 Y 轴 执行此操作。

最佳答案

我会先对模型进行一些更改,以使其显示完整图片。时间戳是数据点的一部分,您需要将它们包装在一起以允许 Live Charts 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>

关于c# - 在 LiveCharts 中针对 DateTime 的一个 X 轴绘制多个 Y 轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55754316/

相关文章:

c++ - 检查一个节点是否在有向图的节点的路径中

c# - 在 X 轴中将 CartesianChart 与 DateAxis 和 DateModel 结合使用

c# - MVVM中的实时UI和LiveCharts更新

c# - Sharepoint 客户端对象模型设置 ModifiedBy 字段

c# - Visual Studio Publish, “PublishTelemetry” 任务无法加载

c# - 从 C# 中的另一个类调用 ConnectionString

c++ - Seg Fault Error C++,创建二维动态数组时

c++ - CGAL 库 Vertex_visibility_graph_2.h 的问题

c# - LiveChart 不显示 x 轴 WPF 上的所有标签

c# - 在关闭和断开IBM MQ.NET客户端上设置超时