WPF编程,Live Charts使用说明(37)——动态曲线2

在这里插入图片描述

本例使用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;
 
            //lets keep in memory only the last 20000 records,
            //to keep everything running faster
            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;
                    //when multi threading avoid indexed calls like -> Values[0] 
                    //instead enumerate the collection
                    //ChartValues/GearedValues returns a thread safe copy once you enumerate it.
                    //TIPS: use foreach instead of for
                    //LINQ methods also enumerate the collections
                    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;
                }
            };
 
            //2 different tasks adding a value every ms
            //add as many tasks as you want to test this feature
            Task.Factory.StartNew(readFromTread);
            Task.Factory.StartNew(readFromTread);
            Task.Factory.StartNew(readFromTread);
            //Task.Factory.StartNew(readFromTread);
            //Task.Factory.StartNew(readFromTread);
            //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
{
    /// <summary>
    /// Interaction logic for SpeedTestView.xaml
    /// </summary>
    public partial class SpeedTestView : UserControl, IDisposable
    {
        public SpeedTestView()
        {
            InitializeComponent();
        }
 
        public void Dispose()
        {
            var vm = (SpeedTestVm) DataContext;
            vm.Values.Dispose();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43307934/article/details/105646094