OxyPlot在wpf中绘制实时动态曲线

版权声明:版权所有,需要请联系作者 https://blog.csdn.net/weixin_42930928/article/details/89143908

1、新建wpf项目:OxyPlotDemo

添加必要的package,主要有:MvvmLight,和OxyPlot.Wpf以及它们的依赖项目,添加完成后,在已安装项里面包含以下5中包。

2、在MainWindow.xaml中添加如下内容:

  • DataContent引用
  • xmlns:oxyplot内容
  • 向grid中添加OxyPlot控件信息

添加OxyPlot控件信息使用了两种方法:

  1. 直接添加<oxyplot:PlotView />,然后在代码中添加坐标轴和Series信息。直接使用Model 绑定ViewModel中的属性,在第21行
  2. 添加<oxyplot:Plot />,然后在Plot中添加坐标轴和Series信息,并将Series中的ItemsSource 绑定ViewModel中的属性,在第22-39行。注意使用Plot时,添加Axes和Series的方式
<Window
    x:Class="OxyPlotDemo.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:local="clr-namespace:OxyPlotDemo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:oxyplot="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Window.DataContext>
        <Binding Path="Main" Source="{StaticResource Locator}" />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <oxyplot:PlotView Model="{Binding Model}" />
        <oxyplot:Plot Title="实时曲线" Grid.Row="1">
            <oxyplot:Plot.Axes>
                <oxyplot:DateTimeAxis Title="时间" />
                <oxyplot:LinearAxis Title="数值" />
            </oxyplot:Plot.Axes>
            <oxyplot:Plot.Series>
                <oxyplot:LineSeries
                    Title="温度"
                    ItemsSource="{Binding TempDataPoints}"
                    MarkerType="Circle"
                    Smooth="True" />
                <oxyplot:LineSeries
                    Title="温度"
                    ItemsSource="{Binding HumiDataPoints}"
                    MarkerType="Circle"
                    Smooth="True" />
            </oxyplot:Plot.Series>
        </oxyplot:Plot>
    </Grid>
</Window>

 3、在ViewModel实现动态数据添加

第一种方式:第57-65行为定义PlotModel,第10-17行为PlotModel初始化处理的PlotModel信息,第19-35行为动态添加曲线数据的功能

第二种方式:第67-85行为定义数据集合信息,第36行-54行为动态添加数据信息功能。

注意:ObservableCollection<>数据的更新一定要在主线程进行,因此第二种方式使用了代理的方式进行添加数据功能

namespace OxyPlotDemo.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            TempDataPoints = new ObservableCollection<DataPoint>();
            HumiDataPoints = new ObservableCollection<DataPoint>();
           
            Model = new PlotModel(){Title = "Simple Example",Subtitle = "using OxyPlot"};
            var series1 = new LineSeries { Title = "温度", MarkerType = MarkerType.Circle,Smooth = true};
            var series2 = new LineSeries { Title = "湿度", MarkerType = MarkerType.Star, Smooth = true ,MarkerStroke = OxyColors.Red};
            var dateTimeAxis1 = new DateTimeAxis();
            dateTimeAxis1.Title = "Time";
            Model.Axes.Add(dateTimeAxis1);
            Model.Series.Add(series1);
            Model.Series.Add(series2);

            Random rd = new Random();
            Task.Run(
                () =>
                    {
                        while (true)
                        {
                            series1.Points.Add(DateTimeAxis.CreateDataPoint(DateTime.Now, rd.Next(10, 30)));
                            series2.Points.Add(DateTimeAxis.CreateDataPoint(DateTime.Now, rd.Next(10, 30)));
                            if (series1.Points.Count > 100)
                            {
                                series1.Points.RemoveAt(0);
                                series2.Points.RemoveAt(0);
                            }
                            Model.InvalidatePlot(true);
                            Thread.Sleep(1000);
                        }
                    });
            Task.Run(
                () =>
                    {
                        while (true)
                        {
                            var date = DateTime.Now;
                            App.Current.Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    TempDataPoints.Add(DateTimeAxis.CreateDataPoint(date, (double)(rd.Next(100, 500) / 10.0)));
                                    HumiDataPoints.Add(DateTimeAxis.CreateDataPoint(date, (double)(rd.Next(500, 800) / 10.0)));
                                    if (TempDataPoints.Count > 300)
                                    {
                                        TempDataPoints.RemoveAt(0);
                                        HumiDataPoints.RemoveAt(0);
                                    }
                                }));
                            Thread.Sleep(1000);
                        }
                    });
        }

        private PlotModel _model;
        /// <summary>
        /// PlotModel
        /// </summary>
        public PlotModel Model
        {
            get { return _model; }
            set { Set(ref _model, value); }
        }

        private ObservableCollection<DataPoint> _tempDataPoints;
        /// <summary>
        /// 温度
        /// </summary>
        public ObservableCollection<DataPoint> TempDataPoints
        {
            get { return _tempDataPoints; }
            set { Set(ref _tempDataPoints, value); }
        }

        private ObservableCollection<DataPoint> _humiDataPoints;
        /// <summary>
        /// 湿度
        /// </summary>
        public ObservableCollection<DataPoint> HumiDataPoints
        {
            get { return _humiDataPoints; }
            set { Set(ref _humiDataPoints, value); }
        }
    }
}

4、两种方式对比

第一种方式,布局文件相对简单,大量代码都需要在ViewModel类中进行处理

第二种方式,布局文件相对复杂,但是在ViewModel类中的代码量相对较少

5、运行效果

 上图为第一种方式,下图为第二种方式


猜你喜欢

转载自blog.csdn.net/weixin_42930928/article/details/89143908
今日推荐