如何让多个轴位于 LiveChart 的两侧?

How do I get multiple axes to be on both sides of a LiveChart?

我有 3 个 Y 轴。我想要图表左侧的 1 个 Y 轴和右侧的 2 个 Y 轴。我尝试了 Position 属性,但似乎没有任何作用。我该怎么做?

这是全部代码。我包括了 MainWindow.xaml、MainWindow.xaml.cs 和 MainViewModel.cs.

这应该是您需要的全部代码。

MainWindow.xaml

<Window x:Class="WpfLiveChartExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfLiveChartExample"
        xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Loaded="TestChart_Loaded">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.DataContext>
            <local:MainViewModel />
        </Grid.DataContext>
        <Grid.Resources>
            <Style x:Key="CleanSeparator" TargetType="lvc:Separator">
                <Setter Property="IsEnabled" Value="False"></Setter>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock x:Name="TestChartTitle" Grid.Row="0" TextWrapping="Wrap">
            You can create multiple axes, just set the Series.ScalesXAt or Series.ScalesYAt properties, you must also add the axis explicitly.
        </TextBlock>
        <lvc:CartesianChart x:Name="TestChart" Grid.Row="2" LegendLocation="Bottom">
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Foreground="DodgerBlue" Title="Blue Axis"   />
                <lvc:Axis Foreground="IndianRed" Title="Red Axis" Position="RightTop">
                    <lvc:Axis.Separator>
                        <lvc:Separator Style="{StaticResource CleanSeparator}"></lvc:Separator>
                    </lvc:Axis.Separator>
                </lvc:Axis>
                <lvc:Axis Foreground="DarkOliveGreen" Title="Green Axis" Position="RightTop">
                    <lvc:Axis.Separator>
                        <lvc:Separator Style="{StaticResource CleanSeparator}"></lvc:Separator>
                    </lvc:Axis.Separator>
                </lvc:Axis>
            </lvc:CartesianChart.AxisY>
            <!--<lvc:CartesianChart.Series>
                <lvc:LineSeries Values="1,5,3,5,3" ScalesYAt="0"/>
                -->
            <!--Scales at blue axis, Axis[0]-->
            <!--
                <lvc:LineSeries Values="20,30,70,20,10"  ScalesYAt="1"/>
                -->
            <!--Scales at red axis, Axis[1]-->
            <!--
                <lvc:LineSeries Values="600,300,200,600,800"  ScalesYAt="2"/>
                -->
            <!--Scales at green axis, Axis[2]-->
            <!--
            </lvc:CartesianChart.Series>-->
        </lvc:CartesianChart>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfLiveChartExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TestChart_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeTestChart();
        }

        private void InitializeTestChart()
        {
            TestChart.Series = (DataContext as MainViewModel).SeriesCollection;
            TestChart.AxisY = (DataContext as MainViewModel).YAxisCollection;
        }
    }
}

MainViewModel.cs

using LiveCharts.Wpf;
using System;
using System.Collections.Generic;

using System.Windows.Media;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LiveCharts.Configurations;
using LiveCharts;

namespace WpfLiveChartExample
{
    public class MainViewModel
    {
        private AxesCollection _yAxisCollection;
        public AxesCollection YAxisCollection { get => _yAxisCollection; }

        private SeriesCollection _seriesCollection;
        public SeriesCollection SeriesCollection { get => _seriesCollection; }

        public MainViewModel()
        {
            _yAxisCollection = new AxesCollection
            {
                new Axis { Title = "Y-Axis 1", Foreground = Brushes.Red },
                new Axis { Title = "Y-Axis 2", Foreground = Brushes.Green },
                new Axis { Title = "Y-Axis 3", Foreground = Brushes.Blue }
            };

            GenerateTestSeries();
        }

        public void GenerateTestSeries()
        {
            LiveCharts.SeriesCollection testSeries = new LiveCharts.SeriesCollection();

            
            var dataPoints = ConvertPointListString("0,3.108 0.814,3.345 1.628,3.342 2.442,3.221 3.256,3.087 4.071,3.004 4.885,2.988 5.699,3.014 6.513,3.03 7.327,2.98 8.141,2.814 8.955,2.514 9.769,2.088 10.584,1.573 11.398,1.004 12.212,0.372");
            var ls1 = new LineSeries
            {
                Name = "Test_Series_1",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 1",
                Values = dataPoints,
                PointGeometry = null
            };

            var dataPoints2 = ConvertPointListString("0,1.359 0.814,1.584 1.628,2.177 2.442,2.737 3.256,3.164 4.071,3.518 4.885,3.858 5.699,4.216 6.513,4.574 7.327,4.863 8.141,5.01 8.955,4.969 9.769,4.721 10.584,4.308 11.398,3.784 12.212,3.15");
            var ls2 = new LineSeries
            {
                Name = "Test_Series_2",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 2",
                Values = dataPoints2,
                PointGeometry = null
            };

            var dataPoints3 = ConvertPointListString("0,0 0.814,27.099 1.628,39.408 2.442,45.311 3.256,50.089 4.071,54.802 4.885,59.645 5.699,64.222 6.513,68.022 7.327,70.766 8.141,72.09 8.955,71.418 9.769,68.126 10.584,60.939 11.398,47.694 12.212,22.742");
            var ls3 = new LineSeries
            {
                Name = "Test_Series_3",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 3",
                Values = dataPoints3,
                PointGeometry = null
            };

            var dataPoints4 = ConvertPointListString("0,0 0.84,0.027 1.68,0.109 2.52,0.245 3.36,0.435 4.2,0.68 5.04,0.979 5.88,1.333 6.72,1.741 7.56,2.203 8.4,2.72");
            var ls4 = new LineSeries
            {
                Name = "Test_Series_4",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 4",
                Values = dataPoints4,
                PointGeometry = null
            };

            var dataPoints5 = ConvertPointListString("0,2.72 8.4,2.72");
            var ls5 = new LineSeries
            {
                Name = "Test_Series_5",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 5",
                Values = dataPoints5,
                PointGeometry = null
            };

            var dataPoints6 = ConvertPointListString("8.4,0 8.4,2.72");
            var ls6 = new LineSeries
            {
                Name = "Test_Series_6",
                Configuration = new CartesianMapper<DataPoint>()
                        .X(dp => dp.X)
                        .Y(dp => dp.Y),
                Title = "Test Series 6",
                Values = dataPoints6,
                PointGeometry = null
            };

            testSeries.Add(ls1);
            testSeries.Add(ls2);
            testSeries.Add(ls3);
            testSeries.Add(ls4);
            testSeries.Add(ls5);
            testSeries.Add(ls6);

            _seriesCollection = testSeries;
        }

        private ChartValues<DataPoint> ConvertPointListString(string pointList, string delimiter = " ", string delimter2 = ",")
        {
            ChartValues<DataPoint> ldp = new ChartValues<DataPoint>();

            char[] pointDelim = delimiter.ToCharArray();
            string[] points = pointList.Split(pointDelim);

            foreach(var point in points)
            {
                char[] coordDelim = delimter2.ToCharArray();
                string[] coord = point.Split(coordDelim);
                ldp.Add(new DataPoint(coord[0], coord[1]));
            }

            return ldp;
        }

    }

    public class DataPoint
    {
        public double X { get; set; }
        public double Y { get; set; }

        public DataPoint()
        {

        }

        public DataPoint(double x, double y)
        {
            X = x;
            Y = y;
        }

        public DataPoint(string x, string y)
        {
            X = Double.Parse(x);
            Y = Double.Parse(y);
        }
    }
}

出于某种原因,XAML 没有采用 Position 值,但如果我在代码隐藏中设置它们,它就会做正确的事情。

public class MainViewModel
    {
        private AxesCollection _yAxisCollection;
        public AxesCollection YAxisCollection { get => _yAxisCollection; }

        private SeriesCollection _seriesCollection;
        public SeriesCollection SeriesCollection { get => _seriesCollection; }

        public MainViewModel()
        {
            _yAxisCollection = new AxesCollection
            {
                new Axis { Title = "Y-Axis 1", MinValue = 0, Position = AxisPosition.LeftBottom, Foreground = Brushes.Red },
                new Axis { Title = "Y-Axis 2", MinValue = 0, Position = AxisPosition.RightTop, Foreground = Brushes.Green },
                new Axis { Title = "Y-Axis 3", MinValue = 0,  Position = AxisPosition.RightTop, Foreground = Brushes.Blue }
            };

            GenerateTestSeries();
        }
        // rest of code stays the same