【问题标题】:WPF Charting Toolkit: How to set a fixed X-axis range while adding real time dataWPF Charting Toolkit:如何在添加实时数据的同时设置固定的 X 轴范围
【发布时间】:2017-07-08 12:12:55
【问题描述】:

我正在做一个基于 WPF Charting Toolkit 的应用程序实时数据图表。我通过串口获取数据。 设置图表代码如下:

    <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>

效果很好,但我仍然需要设置 X 轴的最大值和最小值。 X值(Value1)是接收样本的数量,Y轴值(Value2)显然是接收样本的具体值。

我的问题是关于 X 轴范围的。

目前,我得到的最小值为 0,最大值为串口当前接收到的最大样本数。

但我想设置一个我想看到的 X 轴的永久范围。

例如我想在 X 轴范围内查看 500 个样本。

表示当样本数超过500时,max应为最高样本数,min应ma​​x-500

主要难点是如何在WPF中设置实时数据??

谁能帮帮我好吗?

更新问题

在@jstreet 建议之后,我正在更新我的问题。

我有这个方法在 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             });          
            }));



        }
    }  

这个 Run() 方法负责接收数据并将其添加到图表中。

在另一个类中,我处理了对即将到来的数据和设置属性 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));
        }
    }
}

如何使@jstreet 的解决方案适应我的背后代码示例??

【问题讨论】:

    标签: c# wpf xaml charts wpftoolkit


    【解决方案1】:

    在您的视图模型中创建一个MinValue 依赖属性并将其绑定到您的轴Minimum 属性。看看:

    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>
    

    查看模型:

    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++;
            });
        }
    }
    

    编辑: 作为记录,我可能不会像下面那样编写这段代码。我在这里这样做只是为了让您继续前进。

    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:

    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);
            }
        }
    }
    

    【讨论】:

    • jstreet,感谢您的回复,这很有帮助,但现在我正在努力使您的解决方案适应我的代码。我已经更新了我上面的问题。 jstreet,您能再看一下并提供任何建议吗??
    • 请看我的编辑
    • 谢谢你,伙计!!这是我想要的。效果很好!顺便说一句,您是如何学习 WPF 的?什么资源,以什么方式?
    • 不客气!请记得将我的帖子标记为已接受。请看这个:What should I do when someone answers my question?.
    • 至于学习,和其他一切一样,熟能生巧...:O)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 2011-11-06
    相关资源
    最近更新 更多