Wykresy? No to może warto użyć Live Charts?

Jeśli komuś nie wystarczają możliwości kontrolki Charts dostarczonej przez Microsoft wraz z Visual Studio to może sięgnąć po rozwiązanie dostarczane przez strony trzecie – takim rozwiązaniem jest Live Charts https://lvcharts.net/

Przy pomocy tego rozwiązania możemy stworzyć bardzo dobrze wyglądające wykresy, które z pewnością będą dobrze prezentować się w aplikacjach tworzonych przez nas. Co jest potrzebne? Jeśli korzystamy z VS (ja korzystam z VS2015) to pobieramy do naszego projektu paczkę Livecharts (albo Livecharts.Wpf) z Nuget Managera. Po zainstalowaniu możemy przejść do działania.

Celem jest uzyskanie takich wykresów:
wykres2
Załóżmy, że projekt będzie wykonany w WPF. W oknie tworzymy grida, którego konfigurujemy tak by były przykładowo trzy wiersze i dwie kolumny. Konfiguracja grida poniżej:

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" MinWidth="100"/>
        </Grid.ColumnDefinitions>

Definicja poszczególnych wykresów w XAML wygląda następująco:

        <Wpf:CartesianChart x:Name="chart1" Series="{Binding series1}" 
                            Margin="10,10,0,0"
                            LegendLocation="Right"
                            Grid.Row="0" Grid.Column="0">
            <Wpf:CartesianChart.AxisX>
                <Wpf:Axis Title="próbki" />
            </Wpf:CartesianChart.AxisX>
            <Wpf:CartesianChart.AxisY>
                <Wpf:Axis Title="wartości" MinValue="0" />
            </Wpf:CartesianChart.AxisY>
        </Wpf:CartesianChart>

        <Wpf:CartesianChart x:Name="chart2" Series="{Binding series2}" 
                            Margin="10,0,0,0"
                            LegendLocation="Right"
                            Grid.Row="1" Grid.Column="0">
            <Wpf:CartesianChart.AxisX>
                <Wpf:Axis Title="próbki" />
            </Wpf:CartesianChart.AxisX>
            <Wpf:CartesianChart.AxisY>
                <Wpf:Axis Title="Temperatura wewnętrzna" MaxValue="40" MinValue="-15" />
            </Wpf:CartesianChart.AxisY>
        </Wpf:CartesianChart>

        <Wpf:CartesianChart x:Name="chart3" Series="{Binding series3}" 
                            Margin="10,0,0,0"
                            LegendLocation="Right"
                            Grid.Row="2" Grid.Column="0">
            <Wpf:CartesianChart.AxisX>
                <Wpf:Axis Title="próbki" />
            </Wpf:CartesianChart.AxisX>
            <Wpf:CartesianChart.AxisY>
                <Wpf:Axis Title="Poziom hałasu"/>
            </Wpf:CartesianChart.AxisY>
        </Wpf:CartesianChart>

W kodzie (pliku *.xaml.cs) dodajemy odwołania do wymaganych przestrzeni nazw”

using LiveCharts;
using LiveCharts.Wpf;

Następnie definiujemy kilka kolekcji typu „SeriesCollection”, które będą odpowiadać za nasze wykresy oraz kilka kolekcji typu „ChartValues” odpowiadających za poszczególne „przebiegi” na wykresach.

        public SeriesCollection series1 { get; set; }
        public SeriesCollection series2 { get; set; }
        public SeriesCollection series3 { get; set; }

        ChartValues<double> val1 = new ChartValues<double>();
        ChartValues<double> val2 = new ChartValues<double>();
        ChartValues<double> val2a = new ChartValues<double>();
        ChartValues<double> val3a = new ChartValues<double>();
        ChartValues<double> val3d = new ChartValues<double>();

W kodzie, po InitializeComponents() umieszczamy kod odpowiedzialny za konfigurację serii:

            series1 = new SeriesCollection {
                new LineSeries
                {
                    Title = "Wartości",
                    LineSmoothness = 0,
                    StrokeThickness = 3,                   
                    //PointGeometry = Geometry.Parse("m 2 2 2 4 4 4 4 2"),
                    Stroke = new SolidColorBrush(Color.FromRgb(116,191,155)),
                    Fill = new SolidColorBrush(Color.FromArgb(15,116,191,155)),
                    PointForeground = new SolidColorBrush(Color.FromRgb(69,93,107)),
                    Values = val1
                }
            };

            series2 = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "Temp wew.",
                    LineSmoothness = 0.2,
                    StrokeThickness = 2,
                    DataLabels = true,                    
                    Values = val2
                },
                new LineSeries
                {
                    Title = "Temp. zew",
                    StrokeThickness = 5,
                    DataLabels = true,
                    Values = val2a
                }
            };

            series3 = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "sin(x)",
                    Values = val3a,
                    LineSmoothness = 0,
                    PointGeometrySize = 0
                },
                new LineSeries
                {
                    Title = "prostokąt",
                    Values = val3d,
                    LineSmoothness = 0,
                    PointGeometrySize = 0
                }
            };
            chart1.DataContext = this;
            chart2.DataContext = this;
            chart3.DataContext = this;

Brakuje teraz tylko wartości, które będą budować wykresy. Wartości musimy wrzucić do kolekcji val1, val2, val2a, val3a, val3d. Za wstawienie wartości do powyższych kolekcji odpowiedzialna jest metoda GenerateValues(), którą musimy wywołać zaraz po InitializeComponent(). Kod metody GenerateValues() zamieszczony jest poniżej:

        Random rnd = new Random();

            val1.Clear();
            val2.Clear();
            val2a.Clear();
            val3a.Clear();
            val3d.Clear();

            for (int i = 0; i < 48; i++)
            {
                val1.Add(Math.Round(5 + rnd.NextDouble(), 1));
                val2.Add(Math.Round( 18 + Math.Log(1+3*i) + 0.75 * rnd.NextDouble(),1));
                val2a.Add(Math.Round(-5 + 5*rnd.NextDouble(), 1));                
            }

            for (int i = 0; i < 720; i=i+10)
            {
                double kat = i * Math.PI / 180;
            }

            for (int i = 0; i < 1440; i = i + 5)
            {
                double kat = i * Math.PI / 180;
                val3a.Add( Math.Sin(kat));
                val3d.Add(Math.Sin(kat) + Math.Sin(3 * kat) / 3 + Math.Sin(5 * kat) / 5 + Math.Sin(7 * kat) / 7 + Math.Sin(11 * kat) / 11 + Math.Sin(13 * kat) / 13 + Math.Sin(17 * kat) / 17 + Math.Sin(19 * kat) / 19 + Math.Sin(23 * kat) / 23 + Math.Sin(29 * kat) / 29 + Math.Sin(31 * kat) / 31 + Math.Sin(37 * kat) / 37 + Math.Sin(41 * kat) / 43);
            }

I to by było na tyle (na chwilę obecną). Sam zaznajamiam się dopiero z Live Charts ale wyglądają one na tyle obiecująco, że pewnie jeszcze coś na ich temat napiszę.

Avatar

Autor: gervee

Pełnoetatowy ojciec małej gromadki, programista(?), "amator" fotograf, "dłubacz" lubiący DIY, miłośnik chmielonego napitku. "Żartowniś" bez poczucia humoru ;).

Dodaj komentarz