How do I correctly update my chart values? (In real time)
Asked Answered
S

3

8

I recently encountered a tool called LiveChart and decided to test it out.

Unfortunately I've been having some problems figuring out how to update the chart values in real time. I'm pretty sure there's a clean and correct way of doing it, but I can't seam to find it.

I would like to be able to update the values through a private void or button.

In my code I'm testing it out with a ToolStripMenu.

[CODE]:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using LiveCharts;
using LiveCharts.WinForms;
using LiveCharts.Wpf;
using PokeShowdown_AccStats_T.Properties;
using LiveCharts.Defaults;

namespace PokeShowdown_AccStats_T
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            //int val1 = int.Parse(Settings.Default.Value1);

            var value1 = new ObservableValue(3);
            var value2 = new ObservableValue(7);
            var value3 = new ObservableValue(10);
            var value4 = new ObservableValue(2);

            //value1.Value = 5;

            cartesianChart1.Series.Add(new LineSeries 
            {
                Values = new ChartValues<ObservableValue> { value1, value2, value3, value4 },
                StrokeThickness = 4,
                StrokeDashArray = new System.Windows.Media.DoubleCollection(20),
                Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(107, 185, 69)),
                Fill = System.Windows.Media.Brushes.Transparent,
                LineSmoothness = 0,
                PointGeometry = null
            });



            cartesianChart1.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(34, 46, 49));

            cartesianChart1.AxisX.Add(new Axis
            {
                IsMerged = true,
                Separator = new Separator
                {
                    StrokeThickness = 1,
                    StrokeDashArray = new System.Windows.Media.DoubleCollection(2),
                    Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(64, 79, 86))
                }
            });
            cartesianChart1.AxisY.Add(new Axis
            {
                IsMerged = true,
                Separator = new Separator
                {
                    StrokeThickness = 1.5,
                    StrokeDashArray = new System.Windows.Media.DoubleCollection(4),
                    Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(64, 79, 86))
                }
            });
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void changeValue1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Settings.Default.Value1 = "10";
            Settings.Default.Save();
            this.Text = Settings.Default.Value1;

        }

        private void changeValue1To3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Settings.Default.Value1 = "3";
            Settings.Default.Save();
            this.Text = Settings.Default.Value1;

        }
    }
}
Stunt answered 4/11, 2016 at 4:29 Comment(1)
Chart supports data-binding. Use data-binding and update data source.Dresden
C
9

Live-Charts tries to keep it simple. The logic is to use a generic collection with the type you need to plot, and then as easy as adding/removing or updating any element in this collection then your chart will be updated.

To answer your question, you normally need to:

public partial class Form1 : Form
{
    private ObservableValue value1;

    public Form1()
    {
        InitializeComponent();

        //int val1 = int.Parse(Settings.Default.Value1);

        value1 = new ObservableValue(3);
        //...

        cartesianChart1.Series.Add(new LineSeries 
        {
            Values = new ChartValues<ObservableValue> { value1, ... },
        });
    }

    private void changeValue1ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        value1.Value = 10;
        Settings.Default.Value1 = "10";
        Settings.Default.Save();
        this.Text = Settings.Default.Value1;

    }
}

Then the library will handle animations and the update

enter image description here

Colic answered 4/11, 2016 at 15:44 Comment(1)
I know this is old but is there any way you can share the logic/code for add, insert, remove, and move all buttons? I have been trying to figure how to implement these but LiveCharts documentation only shows how to update the Values variable for a Series by replacing the entire Values variable with another ChartValues variable which ends up redrawing the entire chart.Corncrib
D
4

Note: The question is about LiveCharts. But this answer is posted based on MSChart. To see the answer about LiveCharts see other answer.

Chart supports data-binding. Use data-binding and update data source then refresh chart. For example:

DataTable table = new DataTable();
Random random = new Random();
private void Form1_Load(object sender, EventArgs e)
{
    table.Columns.Add("X", typeof(int));
    table.Columns.Add("Y", typeof(int));
    for (int i = 0; i < 10; i++)
        table.Rows.Add(i+1, random.Next(100));
    chart1.Series[0].ChartType = 
        System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column;
    chart1.Series[0].XValueMember = "X";
    chart1.Series[0].YValueMembers = "Y";
    chart1.DataSource = table;
    chart1.ChartAreas[0].AxisX.Interval = 1;
    chart1.ChartAreas[0].AxisX.Minimum = 0;
    chart1.ChartAreas[0].AxisX.Maximum = 10;
    chart1.ChartAreas[0].AxisY.Interval = 10;
    chart1.ChartAreas[0].AxisY.Minimum = 0;
    chart1.ChartAreas[0].AxisY.Maximum = 100;
    chart1.DataBind();
    var timer = new Timer() { Interval= 300};
    timer.Tick += timer_Tick;
    timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
    for (int i = 0; i < 10; i++)
        table.Rows[i][1]= random.Next(100);
    chart1.DataBind();
}

enter image description here

Dresden answered 4/11, 2016 at 5:29 Comment(5)
This is not what the OP is asking, he is asking abut Live-ChartsColic
@Colic It seems I missed and mistakenly removed livecharts tag in edit. Yes the question is about livecharts.Dresden
@bto Also you/other anyone who downvoted the answer don't need donwvote an answer just to fade it. This post will be useful for future readers who wants to do the trick using mschart. You can post a good answer instead, no need to fade other answers.Dresden
Sorry, I wanted to remove the down vote, but it was too late, I know your answer is also helpfulColic
@Colic No problem. I edited the answer and you can do it now.Dresden
A
0

Hi for Pie chart you can upload the value in this easy way:

code Behind:

/// <summary>
/// Interaction logic for StatusChart.xaml
/// </summary>
public partial class StatusChart : UserControl
{
    #region - Values -
    private List<Double> values;
    public List<Double> Values
    {
         
        get => values;
        set
        {
            if (value is null) throw new NullReferenceException();
            if (value.Count > PieChart.Series.Count) throw new IndexOutOfRangeException();

            for(int serie = 0; serie < PieChart.Series.Count; serie++)
            {
                PieChart.Series[serie].ActualValues[0] = values[serie];
            }

            PieChart.Series.ForEach((i, s) => s.ActualValues[0] = value[i]);
        }
    }
    #endregion
    public StatusChart()
    {
        InitializeComponent();
        
        values = Enumerable.Repeat(1D, PieChart.Series.Count).ToList();
        
        PointLabel = chartPoint => string.Format(new CultureInfo("en-US"), "{0:#0}s", chartPoint.Y);

        GridRoot.DataContext = this;
    }
    public Func<ChartPoint, string> PointLabel { get; set; }

    /// <summary>
    /// method to enalrge the slice (part of pie chart) 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="chartpoint"></param>
    private void Chart_OnDataClick(object sender, ChartPoint chartpoint)
    {
        var chart = (LiveCharts.Wpf.PieChart)chartpoint.ChartView;

        //clear selected slice.
        foreach (PieSeries series in chart.Series)
            series.PushOut = 0;

        var selectedSeries = (PieSeries)chartpoint.SeriesView;
        selectedSeries.PushOut = 7;
    }             
}

and xaml code:

<UserControl x:Class="StatusChart"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="500"
         d:DataContext="{d:DesignInstance local:StatusChart}">

<Grid x:Name="GridRoot">
    <lvc:PieChart x:Name="PieChart" LegendLocation="Bottom" DataClick="Chart_OnDataClick" Hoverable="False"><!-- DataTooltip="{x:Null}">-->
        <lvc:PieChart.Series>
            
            <lvc:PieSeries Title="serie1" 
                           Values="1" DataLabels="True" LabelPoint="{Binding PointLabel}">
            </lvc:PieSeries>

            <lvc:PieSeries Title="serie2" 
                           Values="1" DataLabels="True" LabelPoint="{Binding PointLabel}">
            </lvc:PieSeries>

            <lvc:PieSeries Title="serie3" Values="1" DataLabels="True" 
                           LabelPoint="{Binding PointLabel}"/>

            <lvc:PieSeries Title="serie4" Values="1" DataLabels="True" 
                           LabelPoint="{Binding PointLabel}">
            </lvc:PieSeries>

            <lvc:PieSeries Title="serie4" Values="1" DataLabels="True" 
                           LabelPoint="{Binding PointLabel}">
            </lvc:PieSeries>
        </lvc:PieChart.Series>            
    </lvc:PieChart>
</Grid>

and just to try the control in a window wpf test put this few lines:

 var temporalSc = Enumerable.Repeat(1D, StatusChart.PieChart.Series.Count).ToList();
            for (var i = 0; i < StatusChart.PieChart.Series.Count; i++)
            {
                temporalSc[i] += rnd.Next(1, 87);
            }

            StatusChart.Values.Clear();
            StatusChart.Values = temporalSc;
Apostle answered 31/8, 2020 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.