I've created a LineChart that has 5 charts. Each has 250 points: 1 point every 1 min. I have a button which moves MinValueX and MaxValueX. And an event UserControl_MouseDown which adds new data to 1 chart. But when I invoke this it needs 15-20 seconds to move or add data to the plot. I think 1250 point isn't a lot. It looks like it draws the entire graph again instead of moving it, or adding new data.
Can I somehow change the rendering behavior to be more optimal?
Here is my LineChart control:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using LiveCharts;
using LiveCharts.Defaults;
using LiveCharts.Wpf;
namespace Chart
{
/// <summary>
/// Interaction logic for LineChart2.xaml
/// </summary>
public partial class LineChart2 : UserControl, INotifyPropertyChanged
{
#region properties
public SeriesCollection SeriesCollection { get; set; }
private Dictionary<string, List<DateTimePoint>> SeriesFullCollection { get; set; }
public Func<double, string> XFormatter { get; set; }
public long AxisStep { get; set; }
public double MinValueX { get; set; }
public double MaxValueX { get; set; }
private DateTime minValueXDate;
public DateTime MinValueXDate
{
get { return minValueXDate; }
set { minValueXDate = value;
MinValueX = value.Ticks;
OnPropertyChanged("MinValueX");
}
}
private DateTime maxValueXDate;
public DateTime MaxValueXDate
{
get { return maxValueXDate; }
set
{
maxValueXDate = value;
MaxValueX = value.Ticks;
OnPropertyChanged("MaxValueX");
}
}
public double MinValueY { get; set; }
public double MaxValueY { get; set; }
public int ChartButtonsId { get; set; }
#endregion
public LineChart2()
{
SeriesFullCollection = new Dictionary<string, List<DateTimePoint>>();
SeriesCollection = new SeriesCollection();
this.Loaded += ControlLoaded;
DataContext = this;
InitializeComponent();
}
private void ControlLoaded(object sender, RoutedEventArgs e)
{
MinValueXDate = DateTime.Now.AddHours(-3.5);
MaxValueXDate = DateTime.Now.AddHours(0.5);
AxisStep = TimeSpan.FromMinutes(15).Ticks;
XFormatter = val => new DateTime((long)val).ToString("HH:mm");
MinValueY = 0; //Test
MaxValueY = 20; //Test
//Test
Text2Add("A");
Text2Add("B");
Text2Add("C");
Text2Add("D");
Text2Add("E");
RefreshCollection();
}
#region Add/Update/Remove
public void AddChart(string title, Dictionary<DateTime, double> data)
{
List<DateTimePoint> dateTimePoints = new List<DateTimePoint>();
foreach (var item in data)
dateTimePoints.Add(new DateTimePoint(item.Key, item.Value));
SeriesFullCollection.Add(title, dateTimePoints);
AddToCollection(title);
}
public void UpdateChart(string title, Dictionary<DateTime, double> data)
{
var series = SeriesCollection.FirstOrDefault(x => x.Title == title);
var seriesfull = SeriesFullCollection.FirstOrDefault(x => x.Key == title);
if (series != null)
foreach (var item in data)
{
series.Values.Add(new DateTimePoint(item.Key, item.Value));
seriesfull.Value.Add(new DateTimePoint(item.Key, item.Value));
}
}
public void RemoveChart(string title)
{
var series = SeriesCollection.FirstOrDefault(x => x.Title == title);
var seriesfull = SeriesFullCollection.FirstOrDefault(x => x.Key == title);
if (series != null)
{
SeriesCollection.Remove(series);
SeriesFullCollection.Remove(seriesfull.Key);
}
RefreshCollection();
}
private void AddToCollection(string title)
{
var seriesfull = SeriesFullCollection.FirstOrDefault(x => x.Key == title);
var l = new LineSeries();
l.Title = seriesfull.Key;
l.Values = new ChartValues<DateTimePoint>();
l.PointGeometrySize = 2;
l.Values.AddRange(seriesfull.Value.Where(x => x.DateTime >= MinValueXDate && x.DateTime <= MaxValueXDate));
SeriesCollection.Add(l);
}
#endregion
#region EventsMethod
public void MoveNext()
{
MinValueXDate = MinValueXDate.AddTicks(AxisStep * 2);
MaxValueXDate = MaxValueXDate.AddTicks(AxisStep * 2);
//RefreshCollection();
}
public void MovePrevious()
{
MinValueXDate = MinValueXDate.AddTicks(-AxisStep * 2);
MaxValueXDate = MaxValueXDate.AddTicks(-AxisStep * 2);
//RefreshCollection();
}
public void ZoomIn()
{
MinValueXDate = MinValueXDate.AddTicks(AxisStep);
MaxValueXDate = MaxValueXDate.AddTicks(-AxisStep);
//RefreshCollection();
}
public void ZoomOut()
{
MinValueXDate = MinValueXDate.AddTicks(-AxisStep);
MaxValueXDate = MaxValueXDate.AddTicks(AxisStep);
//RefreshCollection();
}
public void ChangeDate()
{
}
#endregion
private void RefreshCollection()
{
SeriesCollection.Clear();
foreach (var item in SeriesFullCollection)
{
var l = new LineSeries();
l.Title = item.Key;
l.Values = new ChartValues<DateTimePoint>();
l.PointGeometrySize = 2;
l.Values.AddRange(item.Value.Where(x => x.DateTime >= MinValueXDate && x.DateTime <= MaxValueXDate));
SeriesCollection.Add(l);
}
}
#region Test
private void Text2Add(string name)
{
var d = new Dictionary<DateTime, double>();
int last = 0;
Random r = new Random();
for (int i = 0; i < 250; i++)
{
var next = r.Next(last == 0 ? 0 : last - 1, last == 20 ? 20 : last + 2);
last = next;
d.Add(DateTime.Now.AddMinutes(-250+ i), next);
}
AddChart(name, d);
}
private int aaaa = 0;
public event PropertyChangedEventHandler PropertyChanged;
private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
{
var d = new Dictionary<DateTime, double>();
int last = 0;
Random r = new Random();
for (int i = 0; i < 10; i++)
{
var next = r.Next(last == 0 ? 0 : last - 1, last == 20 ? 20 : last + 2);
last = next;
d.Add(DateTime.Now.AddMinutes(aaaa + i), next);
}
aaaa += 10;
UpdateChart("A", d);
}
#endregion
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MinValueXDate = MinValueXDate.AddTicks(AxisStep * 2);
MaxValueXDate = MaxValueXDate.AddTicks(AxisStep * 2);
}
}
}
And Xaml:
<UserControl x:Class="Chart.LineChart2"
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"
xmlns:local="clr-namespace:Chart"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="800" MouseDown="UserControl_MouseDown">
<Grid Background="White">
<lvc:CartesianChart Series="{Binding SeriesCollection}" LegendLocation="Right" >
<lvc:CartesianChart.AxisY>
<lvc:Axis Title="Value" MinValue="{Binding MinValueY}" MaxValue="{Binding MaxValueY}"></lvc:Axis>
</lvc:CartesianChart.AxisY>
<lvc:CartesianChart.AxisX>
<lvc:Axis LabelFormatter="{Binding XFormatter}" MinValue="{Binding MinValueX}" MaxValue="{Binding MaxValueX}">
<lvc:Axis.Separator>
<lvc:Separator Step="{Binding AxisStep}" />
</lvc:Axis.Separator>
</lvc:Axis>
</lvc:CartesianChart.AxisX>
</lvc:CartesianChart>
<Button Height="20" Width="50" Click="Button_Click" Margin="740,10,10,270"/>
</Grid>
</UserControl>
There is a link to page with peformance tips.
Suggested posibilities for better performance are:
So in your case, I would try at least first and last suggestion.