Question:
How to create a graph in WPF with x,y coordinates and the ability to create different curves? I tried to use Chart but I don't know how to create Chart element in code.
Answer:
There are many libraries that allow you to build various types of graphs in WPF
projects.
A few of them:
The choice of programming language ( F#
) for small examples of use was left to one's own discretion, since it was not clearly indicated which one is preferable.
1. OxyPlot supports various types of plots, including LineSeries
, PieSeries
, BarSeries
,… Among the shortcomings – weak documentation. The problem has existed for a long time, but, unfortunately, no work is being done in this direction. Thus, finding the answer to the question of interest is quite difficult. But since the library has already gained some popularity, there are quite a few questions (with answers 🙂 ) on it in English SO
that should help.
To make the answer more complete, let's consider a simple example – plotting two functions sin
and cos
with the ability to check both lines, either of them or not at all.
Oxyplot:
xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
XAML:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="b2v" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<oxy:Plot Title="Пример графика с OxyPlot">
<oxy:Plot.Series>
<oxy:LineSeries Title="Cos(x) "
ItemsSource="{Binding SPoints}"
Visibility="{Binding ElementName=one,
Converter={StaticResource ResourceKey=b2v},
Path=IsChecked}"
Color="Blue" />
<oxy:LineSeries Title="Sin(x)"
ItemsSource="{Binding CPoints}"
Visibility="{Binding ElementName=two,
Converter={StaticResource ResourceKey=b2v},
Path=IsChecked}"
Color="Red" />
</oxy:Plot.Series>
</oxy:Plot>
<CheckBox Name="one" Grid.Row="1" Content="Blue" />
<CheckBox Name="two" Grid.Row="2" Content="Red" />
</Grid>
MainViewModel:
open OxyPlot
…
type MainViewModel() =
let x = -5.0
let y = 5.0
let range = [x..0.1..y]
let sindata =
range
|> List.map(fun value -> value, sin value)
|> List.map(DataPoint)
let cosdata =
range
|> List.map(fun value -> value, cos value)
|> List.map(DataPoint)
member __.SPoints = sindata
member __.CPoints = cosdata
2. LiveCharts is a rapidly growing library. Of the main advantages – documentation. Disadvantages – bugs, which, however, are quite successfully corrected. In addition to the standard set of chart types, it supports 180° Gauge
, Bubble series
. In addition, it is planned to add support for some other types – Countour Maps
. If the documentation is not enough to find the answer to the question, you can write in the chat ( gitter
).
The example is almost the same as the previous one, only without the ability to influence the displayed graphs. This is due to the fact that binding to controls does not work at the moment. Therefore, you need to create a property in the VM
and bind to it.
XAML:
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
<Grid>
<lvc:CartesianChart LegendLocation="Right">
<lvc:CartesianChart.Series>
<lvc:LineSeries PointGeometry="{x:Null}" Fill="Transparent"
StrokeThickness="3" Title="Cos"
Values="{Binding CPoints}" />
<lvc:LineSeries PointGeometry="{x:Null}" Fill="Transparent"
StrokeThickness="3" Title="Sin"
Values="{Binding SPoints}" />
</lvc:CartesianChart.Series>
</lvc:CartesianChart>
</Grid>
VM:
open LiveCharts
open LiveCharts.Configurations
type LiveChartsVM() =
let x = -5.0
let y = 5.0
let range = [x..0.1..y]
let sindata =
range
|> List.map(fun value -> value, sin value)
|> ChartValues
let cosdata =
range
|> List.map(fun value -> value, cos value)
|> ChartValues
do
let mapper = Mappers.Xy<float * float>().X(fst).Y(snd)
LiveCharts.Charting.For<float * float>(mapper, SeriesOrientation.Horizontal)
member __.SPoints = sindata
member __.CPoints = cosdata