2017-07-08 49 views
2

我正在做一個基於WPF圖表工具包的應用程序實時數據製圖。我通過串口獲取數據。 設置圖表的代碼如下:WPF圖表工具包:如何​​設置固定的X軸範圍,同時添加實時數據

<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和maximinum作爲串口在當前時刻接收的最高採樣數。

但我想設置一個我想看到的X軸的永久性範圍。

例如,我想查看500個樣本的X軸範圍。

這意味着當樣本數量超過500時,最大值應該是最高採樣數,最小值應該是max-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()方法負責接收數據並將其添加到圖表中。

在另一類我正在添加上DATAS和設置屬性Valeu1和值2反應的手柄:

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的背後的代碼示例解決我?

回答

1

在您的視圖模型中創建一個MinValue依賴屬性,並將其綁定到您的軸Minimum屬性。請看:

enter image description here

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

編輯:爲了記錄,我可能不會像下面那樣編寫此代碼。我在這裏做,只有這樣你才能繼續前進。

enter image description here

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

jstreet,感謝您的答覆是有益的,但現在我strugg讓您的解決方案適應我的代碼。 我已經更新了我上面的問題。 jstreet,請再次看看並給出任何建議? –

+1

請參閱我的**編輯**。 – jsanalytics

+0

謝謝,夥計!這是我想要的。它工作得很好!順便說一句,你是如何學習WPF的?什麼資源,以什麼方式? –

相關問題