使用LiveCharts常数更改示例来基于时间和串行端口的读数



好吧,所以我基本上想使此图替换日期,并根据停止手表绘制X轴。然后,我希望来自串行端口的数据来绘制Y轴上的数据。这一切都应该在按下按钮的按下。

这是我遵循的示例:

https://lvcharts.net/app/examples/v1/wpf/constant changes

它的问题是它使用系统时间而不是某种停止手表。我正在使用WPF,很想扩大此图的能力。

如果有人可以通过Skype或其他东西帮助我。请让我知道!

最终,我希望能够从图表中获取所有数据并将其保存在某个地方。因此,我可以稍后与以前的几点进行比较。

谢谢!

mainwindow.cs.xaml

<Window x:Class="TestChartProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestChartProject"
    xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<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:1" Hoverable="True" 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>

mainwindow.cs

    private double _axisMax;
    private double _axisMin;
    private double _trend;
    public MainWindow()
    {
        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.Session.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(1);
            var now = DateTime.Now;

            _trend = r.Next(100);
            ChartValues.Add(new MeasureModel
            {
                Session = now,
                Value = _trend
            });
            SetAxisLimits(now);
            //lets only use the last 150 values
            if (ChartValues.Count > 10) 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
}

MeasureModel

    public class MeasureModel
{
    public DateTime Session { get; set; }
    public double Value { get; set; }
}

基于我认为您需要的东西,也许这对您有帮助:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //used to generate random values
        var r = new Random();
        var t = 0d;
        //lets instead plot elapsed milliseconds and value
        var mapper = Mappers.Xy<MeasureModel>()
            .X(x => x.ElapsedMilliseconds)
            .Y(x => x.Value);
        //save the mapper globally         
        Charting.For<MeasureModel>(mapper);
        Values = new ChartValues<MeasureModel>();
        var sw = new Stopwatch();
        sw.Start();
        Task.Run(() =>
        {
            while (true)
            {
                Thread.Sleep(500);
                //we add the lecture based on our StopWatch instance
                Values.Add(new MeasureModel
                {
                    ElapsedMilliseconds = sw.ElapsedMilliseconds,
                    Value = t += r.Next(0,10)
                });
            }
        });
        DataContext = this;
    }
    public ChartValues<MeasureModel> Values { get; set; }
}
public class MeasureModel
{
    public double ElapsedMilliseconds { get; set; }
    public double Value { get; set; }
}

xaml:

<lvc:CartesianChart>
        <lvc:CartesianChart.Series>
            <lvc:LineSeries Values="{Binding Values}" />
        </lvc:CartesianChart.Series>
    </lvc:CartesianChart>

相关内容

  • 没有找到相关文章