Automatic Updates
This web site builds the control from code behind but you could also grab it from the toolbox, this sample also uses a ViewModel to populate the properties of the control(s) in this sample.

This example uses the LineSeries
class but it works the same for any series in the library
View model
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
namespace ViewModelsSamples.Lines.AutoUpdate;
public partial class ViewModel : ObservableObject
{
private readonly Random _random = new();
private readonly ObservableCollection<ObservableValue> _observableValues;
public ViewModel()
{
// Use ObservableCollections to let the chart listen for changes (or any INotifyCollectionChanged). // mark
_observableValues = new ObservableCollection<ObservableValue>
{
// Use the ObservableValue or ObservablePoint types to let the chart listen for property changes // mark
// or use any INotifyPropertyChanged implementation // mark
new ObservableValue(2),
new(5), // the ObservableValue type is redundant and inferred by the compiler (C# 9 and above)
new(4),
new(5),
new(2),
new(6),
new(6),
new(6),
new(4),
new(2),
new(3),
new(4),
new(3)
};
Series = new ObservableCollection<ISeries>
{
new LineSeries<ObservableValue>
{
Values = _observableValues,
Fill = null
}
};
// in the following sample notice that the type int does not implement INotifyPropertyChanged
// and our Series.Values property is of type List<T>
// List<T> does not implement INotifyCollectionChanged
// this means the following series is not listening for changes.
// Series.Add(new ColumnSeries<int> { Values = new List<int> { 2, 4, 6, 1, 7, -2 } }); // mark
}
public ObservableCollection<ISeries> Series { get; set; }
[RelayCommand]
public void AddItem()
{
var randomValue = _random.Next(1, 10);
_observableValues.Add(new(randomValue));
}
[RelayCommand]
public void RemoveItem()
{
if (_observableValues.Count == 0) return;
_observableValues.RemoveAt(0);
}
[RelayCommand]
public void UpdateItem()
{
var randomValue = _random.Next(1, 10);
// we grab the last instance in our collection
var lastInstance = _observableValues[_observableValues.Count - 1];
// finally modify the value property and the chart is updated!
lastInstance.Value = randomValue;
}
[RelayCommand]
public void ReplaceItem()
{
var randomValue = _random.Next(1, 10);
var randomIndex = _random.Next(0, _observableValues.Count - 1);
_observableValues[randomIndex] = new(randomValue);
}
[RelayCommand]
public void AddSeries()
{
// for this sample only 5 series are supported.
if (Series.Count == 5) return;
Series.Add(
new LineSeries<int>
{
Values = new List<int>
{
_random.Next(0, 10),
_random.Next(0, 10),
_random.Next(0, 10)
}
});
}
[RelayCommand]
public void RemoveSeries()
{
if (Series.Count == 1) return;
Series.RemoveAt(Series.Count - 1);
}
}
Form code behind
using System.Threading.Tasks;
using System.Windows.Forms;
using LiveChartsCore.SkiaSharpView.WinForms;
using ViewModelsSamples.Lines.AutoUpdate;
namespace WinFormsSample.Lines.AutoUpdate;
public partial class View : UserControl
{
private readonly CartesianChart _cartesianChart;
private readonly ViewModel _viewModel;
private bool? _isStreaming = false;
public View()
{
InitializeComponent();
Size = new System.Drawing.Size(100, 100);
_viewModel = new ViewModel();
_cartesianChart = new CartesianChart
{
Series = _viewModel.Series,
// out of livecharts properties...
Location = new System.Drawing.Point(0, 50),
Size = new System.Drawing.Size(100, 50),
Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom
};
Controls.Add(_cartesianChart);
var b1 = new Button { Text = "Add item", Location = new System.Drawing.Point(0, 0) };
b1.Click += (object sender, System.EventArgs e) => _viewModel.AddItem();
Controls.Add(b1);
var b2 = new Button { Text = "Replace item", Location = new System.Drawing.Point(80, 0) };
b2.Click += (object sender, System.EventArgs e) => _viewModel.ReplaceItem();
Controls.Add(b2);
var b3 = new Button { Text = "Remove item", Location = new System.Drawing.Point(160, 0) };
b3.Click += (object sender, System.EventArgs e) => _viewModel.RemoveItem();
Controls.Add(b3);
var b4 = new Button { Text = "Add series", Location = new System.Drawing.Point(240, 0) };
b4.Click += (object sender, System.EventArgs e) => _viewModel.AddSeries();
Controls.Add(b4);
var b5 = new Button { Text = "Remove series", Location = new System.Drawing.Point(320, 0) };
b5.Click += (object sender, System.EventArgs e) => _viewModel.RemoveSeries();
Controls.Add(b5);
var b6 = new Button { Text = "Constant changes", Location = new System.Drawing.Point(400, 0) };
b6.Click += OnConstantChangesClick;
Controls.Add(b6);
}
private async void OnConstantChangesClick(object sender, System.EventArgs e)
{
_isStreaming = _isStreaming is null ? true : !_isStreaming;
while (_isStreaming.Value)
{
_viewModel.RemoveItem();
_viewModel.AddItem();
await Task.Delay(1000);
}
}
private void B1_Click(object sender, System.EventArgs e)
{
throw new System.NotImplementedException();
}
}