如何使用动态数据显示在 wpf 中的一个 x-y 平面中添加多个图形

Posted

技术标签:

【中文标题】如何使用动态数据显示在 wpf 中的一个 x-y 平面中添加多个图形【英文标题】:How to add mutiple graph in one x-y plane in wpf using DynamicDataDisplay 【发布时间】:2017-04-20 10:13:46 【问题描述】:

我必须使用 WPF 创建多个类似 http://prntscr.com/dfn836 的图形(我们在一个平面上有 4 个不同颜色的图形)。

我有 DynamicDataDisplaySample,它只显示一个正弦曲线图,但我的情况是我必须在同一个 x-y 轴(电压-时间轴)上显示多个图(让我们在这里说)。我有一组点可以使这两个图在同一平面上。

  List<double> points_x_y_Graph1 = new List<double>()  0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1, 0.2, 0.3 ;
  List<double> points_x_y_Graph2 = new List<double>()  0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0,0.1, 0.2, 0.3 ;

关于如何在一个电压时间轴上制作两个图表,我的想法是为两个图表添加点,如下所示:

//This is for first graph
voltagePointCollection.Add(new VoltagePoint(points_x_y_Graph2[i], points_x_y_Graph2[i]));
//This is for second Graph
voltagePointCollection.Add(new VoltagePoint(points_x_y_Graph1[i], points_x_y_Graph1[i])); 

但是我发现了什么(见这里http://prntscr.com/dfsy5e)。

我的完整代码是:

 public partial class MainWindow : Window, INotifyPropertyChanged
    
        List<double> points_x_y_Graph1 = new List<double>()  0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1, 0.2, 0.3 ;
        List<double> points_x_y_Graph2 = new List<double>()  0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0,0.1, 0.2, 0.3 ;
        private int _maxVoltage; private int _minVoltage;
        public int MaxVoltage
        
            get  return _maxVoltage; 
            set  _maxVoltage = value; this.OnPropertyChanged("MaxVoltage"); 
               
        public int MinVoltage
        
            get  return _minVoltage; 
            set  _minVoltage = value; this.OnPropertyChanged("MinVoltage"); 
        

        public VoltagePointCollection voltagePointCollection;
        DispatcherTimer updateCollectionTimer;
        private int i = 0;

        public MainWindow()
        
            InitializeComponent();
            this.DataContext = this;

            voltagePointCollection = new VoltagePointCollection();

            updateCollectionTimer = new DispatcherTimer();
            updateCollectionTimer.Interval = TimeSpan.FromMilliseconds(10);
            updateCollectionTimer.Tick += new EventHandler(updateCollectionTimer_Tick);
            updateCollectionTimer.Start();         

            var ds = new EnumerableDataSource<VoltagePoint>(voltagePointCollection);
            ds.SetXMapping(x => x.time);
            ds.SetYMapping(y => y.Voltage);  

            plotter.AddLineGraph(ds, Colors.Green, 2, "Volts"); 
            MaxVoltage = 1;
            MinVoltage = -1;            
        

        void updateCollectionTimer_Tick(object sender, EventArgs e)
        
            if (i >= points_x_y.Count) 
             i = 0; 
        //For first graph
        voltagePointCollection.Add(new VoltagePoint(points_x_y_Graph2[i], points_x_y_Graph2[i]));
        //For second graph
        voltagePointCollection.Add(new VoltagePoint(points_x_y_Graph1[i], points_x_y_Graph1[i])); // To add one more graph
            i++;
               

        #region INotifyPropertyChanged members
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        
            if (PropertyChanged != null)
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        
        #endregion
    

Xaml 代码:

<Window x:Class="DynamicDataDisplaySample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
        Title="MainWindow" Height="600" Width="800">
    <Grid>
        <d3:ChartPlotter x:Name="plotter" Grid.Row="1" Grid.Column="1">
            <d3:ChartPlotter.HorizontalAxis>
                <d3:HorizontalDateTimeAxis Name="dateAxis"/>
            </d3:ChartPlotter.HorizontalAxis>
            <d3:Header FontFamily="Georgia" Content="Voltage chart"/>
            <d3:VerticalAxisTitle FontFamily="Georgia" Content="Voltage [V]" />
            <d3:HorizontalAxisTitle FontFamily="Georgia" Content="Time"/>
            <d3:HorizontalLine Value="Binding MaxVoltage" Stroke="Red" StrokeThickness="2"/>
            <d3:HorizontalLine Value="Binding MinVoltage" Stroke="Red" StrokeThickness="2"/>
        </d3:ChartPlotter>
    </Grid>
</Window>

其他两个类:

 public class VoltagePointCollection : RingArray <VoltagePoint>
    
        private const int TOTAL_POINTS = 300;

        public VoltagePointCollection()
            : base(TOTAL_POINTS) // here i set how much values to show 
            
        
    

    public class VoltagePoint
            
        public DateTime Date  get; set; 
        public double time  get; set; 

        public double Voltage  get; set; 

        public VoltagePoint(double voltage, double time)
        
            this.Voltage = voltage;
            this.time = time;
        
    

如何在一个 x-y 轴上制作这两个图表,就像开始时显示的链接一样,其中包含一个 x-y 轴上的 4 个图表。

【问题讨论】:

【参考方案1】:

基本上,您需要再次调用AddLineGraph,并提供相应的关联数据。我做了一些最小的修改,足以让它工作,包括你的数据。请看下面:

XAML:

<Grid>
    <d3:ChartPlotter x:Name="plotter" Grid.Row="1" Grid.Column="1">
        <!--
        <d3:ChartPlotter.HorizontalAxis>
            <d3:HorizontalDateTimeAxis Name="dateAxis"/>
        </d3:ChartPlotter.HorizontalAxis>
        -->
        <d3:Header FontFamily="Georgia" Content="Voltage chart"/>
        <d3:VerticalAxisTitle FontFamily="Georgia" Content="Voltage [V]" />
        <d3:HorizontalAxisTitle FontFamily="Georgia" Content="Time"/>
        <d3:HorizontalLine Value="Binding MaxVoltage" Stroke="Red" StrokeThickness="2"/>
        <d3:HorizontalLine Value="Binding MinVoltage" Stroke="Red" StrokeThickness="2"/>
    </d3:ChartPlotter>
</Grid>

主窗口:

public partial class MainWindow : Window, INotifyPropertyChanged

    List<double> points_x_y_Graph1 = new List<double>()  0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.9, 0.8, 0.7 ;
    List<double> points_x_y_Graph2 = new List<double>()  0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0, 0.1, 0.2, 0.3 ;
    private int _maxVoltage; private int _minVoltage;

    public int MaxVoltage
    
        get  return _maxVoltage; 
        set  _maxVoltage = value; this.OnPropertyChanged("MaxVoltage"); 
    
    public int MinVoltage
    
        get  return _minVoltage; 
        set  _minVoltage = value; this.OnPropertyChanged("MinVoltage"); 
    

    public VoltagePointCollection voltagePointCollection1;
    public VoltagePointCollection voltagePointCollection2;
    DispatcherTimer updateCollectionTimer;
    private int i = 0;

    public MainWindow()
    
        InitializeComponent();
        this.DataContext = this;


        updateCollectionTimer = new DispatcherTimer();
        updateCollectionTimer.Interval = TimeSpan.FromMilliseconds(500);
        updateCollectionTimer.Tick += new EventHandler(updateCollectionTimer_Tick);
        updateCollectionTimer.Start();

        voltagePointCollection1 = new VoltagePointCollection();
        var ds1 = new EnumerableDataSource<VoltagePoint>(voltagePointCollection1);
        ds1.SetXMapping(x => x.time);
        ds1.SetYMapping(y => y.Voltage);

        plotter.AddLineGraph(ds1, Colors.Green, 2, "Volts 1");
        MaxVoltage = 1;
        MinVoltage = -1;

        voltagePointCollection2 = new VoltagePointCollection();
        var ds2 = new EnumerableDataSource<VoltagePoint>(voltagePointCollection2);
        ds2.SetXMapping(x => x.time);
        ds2.SetYMapping(y => y.Voltage);

        plotter.AddLineGraph(ds2, Colors.Blue, 2, "Volts 2");
    

    void updateCollectionTimer_Tick(object sender, EventArgs e)
    
        if (i < points_x_y_Graph1.Count)
        
            // i = 0; 
            //For first graph
            voltagePointCollection1.Add(new VoltagePoint(points_x_y_Graph1[i], i));
            //For second graph
            voltagePointCollection2.Add(new VoltagePoint(points_x_y_Graph2[i], i)); // To add one more graph
            i++;
        
    

    #region INotifyPropertyChanged members
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    
        if (PropertyChanged != null)
            this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
    
    #endregion

【讨论】:

以上是关于如何使用动态数据显示在 wpf 中的一个 x-y 平面中添加多个图形的主要内容,如果未能解决你的问题,请参考以下文章

c# wpf中如何向expander中动态添加xml中的内容

改变动态数据显示未来的图例 wpf

如何动态居中图形

动态数据显示 - WPF - 需要将文本添加到画布 - C#

如何使用wpf中的复选框开发树视图?

在WPF中MessageBox的显示如何定义其参数