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

在这里插入图片描述

在此示例中,我们将模拟每300毫秒读取一次的恒定数据,并使用具有DateTime和double属性的自定义类型 ,在这种情况下,我们将禁用X轴上的动画以获得更好的视觉效果。

在下一个示例中,如果将计时器间隔减小到比Chart.AnimationsSpeed属性更低的频率(默认值为500ms),则可能会注意到仅在动画结束时如何更新图表,图表更新器频率与Chart.AnimationsSpeed属性直接相关。

如果您的数据更新频率低于动画速度,建议也降低动画速度属性(Chart.AnimationsSpeed = TimeSpan.FromMilliseconds(50)),或者您可以在极端情况下禁用动画(Chart.DisableAnimations = true ;)。

自定义类

using System;
 
namespace Wpf.CartesianChart.ConstantChanges
{
    public class MeasureModel
    {
        public DateTime DateTime { get; set; }
        public double Value { get; set; }
    }
}

后台:

using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using LiveCharts;
using LiveCharts.Configurations;
 
namespace Wpf.CartesianChart.ConstantChanges
{
    public partial class ConstantChangesChart : UserControl, INotifyPropertyChanged
    {
        private double _axisMax;
        private double _axisMin;
        private double _trend;
 
        public ConstantChangesChart()
        {
            InitializeComponent();
 
            //To handle live data easily, in this case we built a specialized type
            //the MeasureModel class, it only contains 2 properties
            //DateTime and Value
            //We need to configure LiveCharts to handle MeasureModel class
            //The next code configures MeasureModel  globally, this means
            //that LiveCharts learns to plot MeasureModel and will use this config every time
            //a IChartValues instance uses this type.
            //this code ideally should only run once
            //you can configure series in many ways, learn more at 
            //http://lvcharts.net/App/examples/v1/wpf/Types%20and%20Configuration
 
            var mapper = Mappers.Xy<MeasureModel>()
                .X(model => model.DateTime.Ticks)   //use DateTime.Ticks as X
                .Y(model => model.Value);           //use the value property as Y
 
            //lets save the mapper globally.
            Charting.For<MeasureModel>(mapper);
 
            //the values property will store our values array
            ChartValues = new ChartValues<MeasureModel>();
 
            //lets set how to display the X Labels
            DateTimeFormatter = value => new DateTime((long) value).ToString("mm:ss");
 
            //AxisStep forces the distance between each separator in the X axis
            AxisStep = TimeSpan.FromSeconds(1).Ticks;
            //AxisUnit forces lets the axis know that we are plotting seconds
            //this is not always necessary, but it can prevent wrong labeling
            AxisUnit = TimeSpan.TicksPerSecond;
 
            SetAxisLimits(DateTime.Now);
 
            //The next code simulates data changes every 300 ms
            
            IsReading = false;
 
            DataContext = this;
        }
 
        public ChartValues<MeasureModel> ChartValues { get; set; }
        public Func<double, string> DateTimeFormatter { get; set; }
        public double AxisStep { get; set; }
        public double AxisUnit { get; set; }
 
        public double AxisMax
        {
            get { return _axisMax; }
            set
            {
                _axisMax = value;
                OnPropertyChanged("AxisMax");
            }
        }
        public double AxisMin
        {
            get { return _axisMin; }
            set
            {
                _axisMin = value;
                OnPropertyChanged("AxisMin");
            }
        }
 
        public bool IsReading { get; set; }
 
        private void Read()
        {
            var r = new Random();
 
            while (IsReading)
            {
                Thread.Sleep(150);
                var now = DateTime.Now;
 
                _trend += r.Next(-8, 10);
 
                ChartValues.Add(new MeasureModel
                {
                    DateTime = now,
                    Value = _trend
                });
 
                SetAxisLimits(now);
 
                //lets only use the last 150 values
                if (ChartValues.Count > 150) ChartValues.RemoveAt(0);
            }
        }
 
        private void SetAxisLimits(DateTime now)
        {
            AxisMax = now.Ticks + TimeSpan.FromSeconds(1).Ticks; // lets force the axis to be 1 second ahead
            AxisMin = now.Ticks - TimeSpan.FromSeconds(8).Ticks; // and 8 seconds behind
        }
 
        private void InjectStopOnClick(object sender, RoutedEventArgs e)
        {
            IsReading = !IsReading;
            if (IsReading) Task.Factory.StartNew(Read);
        }
 
        #region INotifyPropertyChanged implementation
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
 
        #endregion
    }
}

前台:

<UserControl x:Class="Wpf.CartesianChart.ConstantChanges.ConstantChangesChart"
             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:constantChanges="clr-namespace:Wpf.CartesianChart.ConstantChanges"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance constantChanges:ConstantChangesChart}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Click="InjectStopOnClick">
            Inject/Stop Data
        </Button>
        <!--Here we disable tooltips and hovering to get a better performance-->
        <lvc:CartesianChart Grid.Row="1" AnimationsSpeed="0:0:0.5" Hoverable="False" DataTooltip="{x:Null}">
            <lvc:CartesianChart.Series>
                <lvc:LineSeries Values="{Binding ChartValues}" 
                                PointGeometry="{x:Null}" 
                                LineSmoothness="1"
                                StrokeThickness="6" 
                                Stroke="#F34336"
                                Fill="Transparent"/>
            </lvc:CartesianChart.Series>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis LabelFormatter="{Binding DateTimeFormatter}" 
                          MaxValue="{Binding AxisMax}" 
                          MinValue="{Binding AxisMin}"
                          Unit="{Binding AxisUnit}">
                    <lvc:Axis.Separator>
                        <lvc:Separator Step="{Binding AxisStep}" />
                    </lvc:Axis.Separator>
                </lvc:Axis>
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

猜你喜欢

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