I have 3 Y-axes. I would like 1 Y-axis on the left and 2 Y-axis on the right of the chart. I tried the Position attribute but that doesn't seem to do anything. How can I do this?
Here is all the code. I've included MainWindow.xaml, MainWindow.xaml.cs, and MainViewModel.cs.
This should be all the code you need.
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);
}
}
}
The XAML for some reason isn't taking the Position values, but if I set them in code-behind it does the right thing.
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