本例使用LiveCharts.Geared,齿轮传动包是一个可选的扩展,提升性能LiveCharts
后台:
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using LiveCharts.Geared;
namespace Geared.Wpf.SpeedTest
{
public class SpeedTestVm : INotifyPropertyChanged
{
private double _trend;
private double _count;
private double _currentLecture;
private bool _isHot;
public SpeedTestVm()
{
Values = new GearedValues<double>().WithQuality(Quality.Highest);
ReadCommand = new RelayCommand(Read);
StopCommand = new RelayCommand(Stop);
CleaCommand = new RelayCommand(Clear);
}
public bool IsReading { get; set; }
public RelayCommand ReadCommand { get; set; }
public RelayCommand StopCommand { get; set; }
public RelayCommand CleaCommand { get; set; }
public GearedValues<double> Values { get; set; }
public double Count
{
get { return _count; }
set
{
_count = value;
OnPropertyChanged("Count");
}
}
public double CurrentLecture
{
get { return _currentLecture; }
set
{
_currentLecture = value;
OnPropertyChanged("CurrentLecture");
}
}
public bool IsHot
{
get { return _isHot; }
set
{
var changed = value != _isHot;
_isHot = value;
if (changed) OnPropertyChanged("IsHot");
}
}
private void Stop()
{
IsReading = false;
}
private void Clear()
{
Values.Clear();
}
private void Read()
{
if (IsReading) return;
const int keepRecords = 20000;
IsReading = true;
Action readFromTread = () =>
{
while (IsReading)
{
Thread.Sleep(1);
var r = new Random();
_trend += (r.NextDouble() < 0.5 ? 1 : -1) * r.Next(0, 10)*.001;
var first = Values.DefaultIfEmpty(0).FirstOrDefault();
if (Values.Count > keepRecords - 1) Values.Remove(first);
if (Values.Count < keepRecords) Values.Add(_trend);
IsHot = _trend > 0;
Count = Values.Count;
CurrentLecture = _trend;
}
};
Task.Factory.StartNew(readFromTread);
Task.Factory.StartNew(readFromTread);
Task.Factory.StartNew(readFromTread);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
辅助类
using System;
using System.Windows.Input;
namespace Geared.Wpf.SpeedTest
{
public class RelayCommand : ICommand
{
private Action _action;
public RelayCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action();
}
public event EventHandler CanExecuteChanged;
}
}
前台:
<UserControl x:Class="Geared.Wpf.SpeedTest.SpeedTestView"
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:speedTest="clr-namespace:Geared.Wpf.SpeedTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<speedTest:SpeedTestVm></speedTest:SpeedTestVm>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap">Here we are adding a value every millisecond from 2 different tasks</TextBlock>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="15">
<Button Command="{Binding ReadCommand}">Start Lecture</Button>
<Button Command="{Binding StopCommand}">Stop</Button>
<Button Command="{Binding CleaCommand}">Clear</Button>
<TextBlock VerticalAlignment="Center" Margin="15 0" Text="{Binding Count, StringFormat=Buffer: {0}}"></TextBlock>
</StackPanel>
<lvc:CartesianChart Grid.Row="2" DisableAnimations="True" DataTooltip="{x:Null}" Hoverable="False">
<lvc:CartesianChart.Resources>
<Style TargetType="lvc:LineSeries">
<Setter Property="StrokeThickness" Value="0"></Setter>
<Setter Property="Fill" Value="#CC2196F3"></Setter>
<Setter Property="LineSmoothness" Value=".3"></Setter>
<Setter Property="AreaLimit" Value="0"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsHot}" Value="true">
<Setter Property="Fill" Value="#CCFF5722"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="lvc:Separator">
<Setter Property="Stroke" Value="#DADADA"></Setter>
<Setter Property="StrokeThickness" Value="2"></Setter>
<Style.Triggers>
<Trigger Property="AxisOrientation" Value="X">
<Setter Property="IsEnabled" Value="False"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</lvc:CartesianChart.Resources>
<lvc:CartesianChart.Series>
<lvc:LineSeries Values="{Binding Values}" PointGeometry="{x:Null}"></lvc:LineSeries>
</lvc:CartesianChart.Series>
<lvc:CartesianChart.AxisX>
<lvc:Axis MaxValue="20500" ShowLabels="False"></lvc:Axis>
</lvc:CartesianChart.AxisX>
<lvc:CartesianChart.AxisY>
<lvc:Axis>
<lvc:Axis.Sections>
<lvc:AxisSection Value="0" StrokeThickness="3" Stroke="#303030"></lvc:AxisSection>
</lvc:Axis.Sections>
</lvc:Axis>
</lvc:CartesianChart.AxisY>
</lvc:CartesianChart>
<TextBlock Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Right"
Margin="40 20" FontSize="110" Foreground="#72000000"
Text="{Binding CurrentLecture, StringFormat={}{0:N1}°}"></TextBlock>
</Grid>
</UserControl>
后台调用:
using System;
using System.Windows.Controls;
namespace Geared.Wpf.SpeedTest
{
public partial class SpeedTestView : UserControl, IDisposable
{
public SpeedTestView()
{
InitializeComponent();
}
public void Dispose()
{
var vm = (SpeedTestVm) DataContext;
vm.Values.Dispose();
}
}
}