如何在OxyPlot图表上绘制多个LineSeries?

13

很抱歉我问了这么多关于 OxyPlot 的问题,但我确实在使用OxyPlot图表控件时遇到了一些困难。

我的项目是以 WPF 格式为基础的,因此我最初使用了托管的 WINFORMS 图表,它能完全胜任并满足我所有需要,直到我需要将一个 WPF 元素叠加在托管的 Winform 图表上。由于"AirSpace"问题,无论我做什么都看不到放置在托管图表上方的 WPF 元素。那时候我决定使用OxyPlot,但它给我带来了不少麻烦。

这是我在 CodePlex 上发布的原始问题! 我在那里得不到太多帮助,所以现在我又在这里尝试一下。

我的问题是:

有没有人知道如何在一个图表上绘制多条线?

我的方法是:

我正在利用 C# 中的 List 数组,并添加一个新的 LineSeries 的副本来保存要绘制的新数据。我的代码如下:

    // Function to plot data
    private void plotData(double numWeeks, double startingSS)
    {

        // Initialize new Salt Split class for acess to data variables
        Salt_Split_Builder calcSS = new Salt_Split_Builder();
        calcSS.compute(numWeeks, startingSS, maxDegSS);

        // Create the OxyPlot graph for Salt Split
        OxyPlot.Wpf.PlotView plot = new OxyPlot.Wpf.PlotView();

        var model = new PlotModel();

        // Add Chart Title
        model.Title = "Salt Split Degradation";

        // Create new Line Series
        LineSeries linePoints = new LineSeries() { StrokeThickness = 1, MarkerSize = 1, Title = numWeeks.ToString() + " weeks" };

        // Add each point to the new series
        foreach (var point in calcSS.saltSplitCurve)
        {
            DataPoint XYpoint = new DataPoint();
            XYpoint = new DataPoint(point.Key, point.Value * 100);
            linePoints.Format("%", XYpoint.Y);
            linePoints.Points.Add(XYpoint);
        }

        listPointAray.Add(linePoints);

        // Define X-Axis
        var Xaxis = new OxyPlot.Axes.LinearAxis();
        Xaxis.Maximum = numWeeks;
        Xaxis.Minimum = 0;
        Xaxis.Position = OxyPlot.Axes.AxisPosition.Bottom;
        Xaxis.Title = "Number of Weeks";
        model.Axes.Add(Xaxis);

        //Define Y-Axis
        var Yaxis = new OxyPlot.Axes.LinearAxis();
        Yaxis.MajorStep = 15;
        Yaxis.Maximum = calcSS.saltSplitCurve.Last().Value * 100;
        Yaxis.MaximumPadding = 0;
        Yaxis.Minimum = 0;
        Yaxis.MinimumPadding = 0;
        Yaxis.MinorStep = 5;
        Yaxis.Title = "Percent Degradation";
        model.Axes.Add(Yaxis);

        // Add Each series to the
        foreach (var series in listPointAray)
        {
            LineSeries newpoints = new LineSeries();
            newpoints = linePoints;
            model.Series.Add(newpoints);
        }

        // Add the plot to the window
        plot.Model = model;
        SaltSplitChartGrid.Children.Add(plot);

    }

当我按下“Graph Data”按钮时,我的代码第一次有效,但在随后的尝试中发生以下错误:

  

无法添加该元素,因为它已经属于 Plot Model。

我想要生成的绘图类型如下所示(使用 WinForms Chart 控件可以正常工作):

Image

每次运行该方法时,我希望有一个新颜色的新行被绘制。


这不是完全的重复,因为我的方法稍有不同。我没有使用数据绑定,但我可能应该尝试一下,所以我也会看看那种方法。 - Hooplator15
3个回答

12

这是我之前在OxyPlot图表上创建多行的方法,关键是为每个系列创建一组DataPoints——在以下示例代码中称为circlePoints和linePoints,然后将它们绑定到CircleSeries和LineSeries:

var xAxis = new DateTimeAxis
{
    Position = AxisPosition.Bottom,
    StringFormat = Constants.MarketData.DisplayDateFormat,
    Title = "End of Day",
    IntervalLength = 75,
    MinorIntervalType = DateTimeIntervalType.Days,
    IntervalType = DateTimeIntervalType.Days,
    MajorGridlineStyle = LineStyle.Solid,
    MinorGridlineStyle = LineStyle.None,
};

var yAxis = new LinearAxis
{
    Position = AxisPosition.Left,
    Title = "Value",
    MajorGridlineStyle = LineStyle.Solid,
    MinorGridlineStyle = LineStyle.None
};

var plot = new PlotModel();
plot.Axes.Add(xAxis);
plot.Axes.Add(yAxis);

var circlePoints = new[]
{
    new ScatterPoint(DateTimeAxis.ToDouble(date1), value1),
    new ScatterPoint(DateTimeAxis.ToDouble(date2), value2),
};

var circleSeries =  new ScatterSeries
{
    MarkerSize = 7,
    MarkerType = MarkerType.Circle,
    ItemsSource = circlePoints
};

var linePoints = new[]
{
    new DataPoint(DateTimeAxis.ToDouble(date1), value1),
    new DataPoint(DateTimeAxis.ToDouble(date2), value2),
};

var lineSeries = new LineSeries
{
    StrokeThickness = 2,
    Color = LineDataPointColor,
    ItemsSource = linePoints
};

plot.Series.Add(circleSeries);
plot.Series.Add(lineSeries);

谢谢,我一回到工作站就会仔细看看并尝试一下。我知道我肯定漏掉了什么。感谢你的帮助! - Hooplator15

7

成功!!!

AwkwardCoder,感谢您的帮助,但我意识到我的错误只是因为我忽略了一些东西!

这是可以工作的代码版本:

        // Make a new plotmodel
    private PlotModel model = new PlotModel();

    // Create the OxyPlot graph for Salt Split
    private OxyPlot.Wpf.PlotView plot = new OxyPlot.Wpf.PlotView();

    // Function to plot data
    private void plotData(double numWeeks, double startingSS)
    {
        List<LineSeries> listPointAray = new List<LineSeries>();

        // Initialize new Salt Split class for acess to data variables
        Salt_Split_Builder calcSS = new Salt_Split_Builder();
        calcSS.compute(numWeeks, startingSS, maxDegSS);

        // Create new Line Series
        LineSeries linePoints = new LineSeries() 
        { StrokeThickness = 1, MarkerSize = 1, Title = numWeeks.ToString() + " weeks" };


        // Add each point to the new series
        foreach (var point in calcSS.saltSplitCurve)
        {
            DataPoint XYpoint = new DataPoint();
            XYpoint = new DataPoint(point.Key, point.Value * 100);
            linePoints.Format("%", XYpoint.Y);
            linePoints.Points.Add(XYpoint);
        }

        listPointAray.Add(linePoints);

        // Add Chart Title
        model.Title = "Salt Split Degradation";

        // Add Each series to the
        foreach (var series in listPointAray)
        {
            // Define X-Axis
            OxyPlot.Axes.LinearAxis Xaxis = new OxyPlot.Axes.LinearAxis();
            Xaxis.Maximum = numWeeks;
            Xaxis.Minimum = 0;
            Xaxis.Position = OxyPlot.Axes.AxisPosition.Bottom;
            Xaxis.Title = "Number of Weeks";
            model.Axes.Add(Xaxis);

            //Define Y-Axis
            OxyPlot.Axes.LinearAxis Yaxis = new OxyPlot.Axes.LinearAxis();
            Yaxis.MajorStep = 15;
            Yaxis.Maximum = calcSS.saltSplitCurve.Last().Value * 100;
            Yaxis.MaximumPadding = 0;
            Yaxis.Minimum = 0;
            Yaxis.MinimumPadding = 0;
            Yaxis.MinorStep = 5;
            Yaxis.Title = "Percent Degradation";
            //Yaxis.StringFormat = "{0.00} %";
            model.Axes.Add(Yaxis);

            model.Series.Add(series);
        }


        // Add the plot to the window

        plot.Model = model;
        plot.InvalidatePlot(true);
        SaltSplitChartGrid.Children.Clear();
        SaltSplitChartGrid.Children.Add(plot);

    }

以下是我所犯的多个错误:
  1. 在我的foreach变量系列循环中,我添加的是已经添加过的原始系列,而不是列表中的下一个变量系列!(愚蠢!)
  2. 每次运行该方法时,我都会创建一个新模型。这意味着每次代码运行时,我都会添加一个已存在于先前模型中的系列。(同样愚蠢!)
  3. 每次都创建一个新图形,并尝试在新图形中添加一个已经属于先前图形的模型。(越来越愚蠢...)
  4. 每次运行该方法时都会向网格中添加图形,所以在重新添加相同图形之前必须清除网格的子元素。
  5. 我没有刷新图形。
这是很多错误,但我已经解决了它。希望这能帮助未来的某个人。另外,我知道我没有使用普通的数据绑定技术,但至少这个方法是有效的。
最终结果:working plot

1
以下是您在使用MVVM方法时,尤其是在XAML中实现类似结果的方法。
视图模型(ViewModel):
public ObservableCollection<DataPoint> DataPointList1 {get;set;}
public ObservableCollection<DataPoint> DataPointList2 {get;set;}
public ObservableCollection<DataPoint> DataPointList3 {get;set;}
public ObservableCollection<DataPoint> DataPointList4 {get;set;}

使用如下的for循环将适当的数据集填充到DataPointList1至DataPointList4中。
for (int i = 0; i < dataList.Count; i++)
{
    DataPointList1 .Add(new DataPoint{dataList[i].XValue,dataList[i].YValue });
}

XAML:
    xmlns:oxy="http://oxyplot.org/wpf"

<oxy:Plot LegendPlacement="Outside" LegendPosition="RightMiddle" Title="Your Chart Title" >
    <oxy:Plot.Axes>
        <oxy:LinearAxis Title="Your X-axis Title" Position="Bottom" IsZoomEnabled="True" />
       <oxy:LinearAxis Title="Your Y-axis Title" Position="Left" IsZoomEnabled="True" />
  </oxy:Plot.Axes>
  <oxy:Plot.Series>
       <oxy:LineSeries Title="Plot1"  Color="Black"  ItemsSource="{Binding DataPointList1 }"/>
       <oxy:LineSeries Title="Plot2"  Color="Green"  ItemsSource="{Binding DataPointList2 }"/>
       <oxy:LineSeries Title="Plot3"  Color="Blue"   ItemsSource="{Binding DataPointList3 }"/>
       <oxy:LineSeries Title="Plot4"  Color="Red" ItemsSource="{Binding DataPointList4 }"/>
   </oxy:Plot.Series>
</oxy:Plot>

但是如何动态地实现这一点呢?也就是说,在设计时如果您不知道 oxy:LineSeries 的数量,该怎么办呢?我需要在运行时将 LineSeries 添加到 oxy:Plot.Series 中... - Erik
您可以在代码后台编程创建LineSeries。 - Bloggrammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接