简体   繁体   English

WPF Charting Toolkit:如何在添加实时数据的同时设置固定的X轴范围

[英]WPF Charting Toolkit: How to set a fixed X-axis range while adding real time data

I'm doing an application real time data charting basing on WPF Charting Toolkit. 我正在基于WPF Charting Toolkit进行应用程序实时数据制图。 I get the datas via serial port. 我通过串口获取数据。 The code of setting chart is below: 设置图表的代码如下:

    <chartingToolkit:Chart  Margin="10,10,10,0" ClipToBounds="True" x:Name="chart1" Title="Chart Title">
        <chartingToolkit:LineSeries IndependentValueBinding="{Binding Value1}" DependentValueBinding="{Binding Value2}" ItemsSource="{Binding}" Background="Transparent" Cursor="No">
            <chartingToolkit:LineSeries.DataPointStyle>
                <Style TargetType="{x:Type chartingToolkit:LineDataPoint}">
                    <Setter Property="Height" Value="0"/>
                    <Setter Property="Width" Value="0" />
                    <Setter Property="Background" Value="Green"/>
                </Style>
            </chartingToolkit:LineSeries.DataPointStyle>
        </chartingToolkit:LineSeries>
    </chartingToolkit:Chart>

It works good but I still need to set maximum and minimum values of X axis. 它工作得很好,但我仍然需要设置X轴的最大值和最小值。 The X Values (Value1) are as number of received samples and the Y axis values (Value2) are obviously as concrete values of the received samples. X值(Value1)是接收样本的数量,Y轴值(Value2)显然是接收样本的具体值。

My question is about the X axis range. 我的问题是关于X轴范围。

Currently, I'm getting minimum as 0 and maximinum as the highest number of sample which the serial port received in current moment. 目前,我的最小值为0和maximinum是串口在当前时刻收到的最高样本数。

But I want to set a permanent range of X axis which I want to see. 但我想设置一个永久的X轴范围,我希望看到它。

For example I want to see on the X axis range of 500 samples. 例如,我想在X轴上看到500个样本的范围。

It means that when the number of samples exceeds 500, the max should be as the highest sample number and the min should be max-500 . 这意味着当样本数超过500时,max应该是最高样本数,min应该是max-500

The main difficulty is how to set it with real time data in WPF?? 主要的难点是如何在WPF中设置实时数据?

Can anyone help me, please?? 有人可以帮帮我吗?

Updated question 更新的问题

I'm updating my question after @jstreet advise. 我在@jstreet建议后更新我的问题。

I have this method which is running in separate thread within MainWindow class, likes below. 我有这个方法在MainWindow类中的单独线程中运行,如下所示。

 public partial class MainWindow : Window 
  {
 public SerialPort serialPort1 = new SerialPort();
    public string rx_str = "";
    public string rx_str_copy;
    public int a;
    public double x, y;


      ObservableCollection<ChartData> chartData;
    ChartData objChartData;
    Thread myThread;

     public MainWindow()
    {
        InitializeComponent();
        string[] port = SerialPort.GetPortNames();
        foreach (string a in port)
        {
            comboPorts.Items.Add(a);
        }
        Array.Sort(port);
        comboPorts.Text = port[0];

        objChartData = new ChartData();
        chartData.Add(objChartData);
        chart1.DataContext = chartData;
        myThread = new Thread(new ThreadStart(Run));


    }

   public void Run()
       {
        while (true)
        {
            serialPort1.Write("a");
            rx_str = serialPort1.ReadTo("b");
            rx_str_copy = rx_str;
            x = a;
            y = Double.Parse(rx_str_copy,     CultureInfo.InvariantCulture);                                               

            a++;

            Dispatcher.Invoke(new Action(delegate
            {

         chartData.Add(new ChartData() { Value1 = x,         
       Value2= y             });          
            }));



        }
    }  

This Run() method is responsible for receiving datas and adding it to the chart. 此Run()方法负责接收数据并将其添加到图表中。

In another class I have handle of reaction on comming datas and settings properties Valeu1 and Value2: 在另一个类中,我处理了对数据和设置属性Valeu1和Value2的反应:

  public class ChartData : INotifyPropertyChanged
   {
    double _Value1;
    double _Value2;


    public double Value1
    {
        get
        {
            return _Value1;
        }
        set
        {
            _Value1 = value;
            OnPropertyChanged("Value1");
        }
    }

    public double Value2
    {
        get
        {
            return _Value2;
        }
        set
        {
            _Value2 = value;
            OnPropertyChanged("Value2");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new   
     PropertyChangedEventArgs(propertyName));
        }
    }
}

How can I adapt @jstreet's solution to my behind code example?? 如何将@jstreet的解决方案应用于我的后台代码示例?

Create a MinValue dependency property in your view model and bind it to your axis Minimum property. 在视图模型中创建MinValue依赖项属性,并将其绑定到轴Minimum属性。 Take a look: 看一看:

在此输入图像描述

XAML: XAML:

<Window
        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:WpfApp31"
        xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" 
        x:Class="WpfApp31.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>
    <Grid>
        <chartingToolkit:Chart  Title="My Sample">
            <chartingToolkit:Chart.Axes>
                <chartingToolkit:LinearAxis Minimum="{Binding MinValue}" Orientation="X"></chartingToolkit:LinearAxis>
            </chartingToolkit:Chart.Axes>
            <chartingToolkit:LineSeries IndependentValueBinding="{Binding Value1}" 
                                        DependentValueBinding="{Binding Value2}" 
                                        ItemsSource="{Binding Data}">
            </chartingToolkit:LineSeries>
        </chartingToolkit:Chart>
    </Grid>
</Window>

View Model: 查看型号:

public class MyViewModel : DependencyObject
{
    public int MinValue
    {
        get { return (int)GetValue(MinValueProperty); }
        set { SetValue(MinValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MinValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MinValueProperty =
        DependencyProperty.Register("MinValue", typeof(int), typeof(MyViewModel), new PropertyMetadata(default(int)));

    public ObservableCollection<MyDataModel> Data { get; set; }

    private Timer serialPort;
    private Random y;
    private int x;
    private int range;

    public MyViewModel()
    {
        range = 10;
        Data = new ObservableCollection<MyDataModel>();
        y = new Random(DateTime.Now.Millisecond);
        serialPort = new Timer(DataReceived, null, 500, 500);
    }
    private void DataReceived(object state)
    {
        Application.Current.Dispatcher.Invoke(() => {
            Data.Add(new MyDataModel { Value1 = x, Value2 = y.Next(10, 90) });
            MinValue = x < range ? 0 : x - range;
            x++;
        });
    }
}

EDIT: For the record, I would probably not write this code quite like below. 编辑:为了记录,我可能不会像下面那样编写这段代码。 I'm doing it here just so you can move forward with it. 我正在这里做,所以你可以继续前进。

在此输入图像描述

XAML: XAML:

<Window
    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:WpfApp1"
    xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" 
    x:Class="WpfApp1.MainWindow"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="10*"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <chartingToolkit:Chart Grid.Row="0"  Margin="10,10,10,0" ClipToBounds="True" x:Name="chart1" Title="Chart Title">
        <chartingToolkit:Chart.Axes>
            <chartingToolkit:LinearAxis Minimum="{Binding MinValue}" Orientation="X"></chartingToolkit:LinearAxis>
        </chartingToolkit:Chart.Axes>
        <chartingToolkit:LineSeries IndependentValueBinding="{Binding Value1}" DependentValueBinding="{Binding Value2}" ItemsSource="{Binding chartData}" Background="Transparent" Cursor="No">
            <chartingToolkit:LineSeries.DataPointStyle>
                <Style TargetType="{x:Type chartingToolkit:LineDataPoint}">
                    <Setter Property="Height" Value="0"/>
                    <Setter Property="Width" Value="0" />
                    <Setter Property="Background" Value="Green"/>
                </Style>
            </chartingToolkit:LineSeries.DataPointStyle>
        </chartingToolkit:LineSeries>
    </chartingToolkit:Chart>

    <Button Grid.Row="1" x:Name="btn1" Click="btn1_Click">START</Button>

</Grid>

CS: CS:

public partial class MainWindow : Window
{
    public double MinValue
    {
        get { return (double)GetValue(MinValueProperty); }
        set { SetValue(MinValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MinValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MinValueProperty =
        DependencyProperty.Register("MinValue", typeof(double), typeof(MainWindow), new PropertyMetadata(default(double)));

    //public SerialPort serialPort1 = new SerialPort();
    //public string rx_str = "";
    //public string rx_str_copy;
    //public int a;
    public double x, y;

    public ObservableCollection<ChartData> chartData { get; set; }
    ChartData objChartData;
    Thread myThread;
    Random r;
    int range = 50;

    public MainWindow()
    {
        InitializeComponent();

        r = new Random();

        DataContext = this;

        /*
        string[] port = SerialPort.GetPortNames();

        foreach (string a in port)
        {
            comboPorts.Items.Add(a);
        }

        Array.Sort(port);
        comboPorts.Text = port[0];
        */

        objChartData = new ChartData();
        chartData = new ObservableCollection<ChartData>();
        chartData.Add(objChartData);
        //chart1.DataContext = chartData;
        myThread = new Thread(new ThreadStart(Run));
    }

    private void btn1_Click(object sender, RoutedEventArgs e)
    {
        myThread.Start();
    }

    public void Run()
    {
        while (true)
        {
            //serialPort1.Write("a");
            //rx_str = serialPort1.ReadTo("b");
            //rx_str_copy = rx_str;

            //x = a;
            //y = Double.Parse(rx_str_copy, CultureInfo.InvariantCulture);

            //a++;

            Dispatcher.Invoke(new Action(delegate
            {
                chartData.Add(new ChartData()
                {
                    Value1 = x,
                    Value2 = r.NextDouble(),
                    //Value2 = y
                });
                MinValue = x < range ? 0 : x - range;
                x++;
            }));

            Thread.Sleep(50);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM