Как построить НЕСКОЛЬКО LineSeries на графике OxyPlot?

Я прошу прощения за то, что задал так много вопросов по OxyPlot, но мне кажется, что я действительно испытываю трудности с использованием элемента управления диаграммой OxyPlot.

Мой проект находится в формате WPF, поэтому я изначально использовал размещенную диаграмму WINFORMS, которая работала как шарм и делал абсолютно все, что мне было нужно, пока мне не нужно было наложить элемент WPF поверх размещенной диаграммы winform. Из-за проблемы с «AirSpace» я не мог видеть элемент WPF, который я поместил поверх размещенной диаграммы, что бы я ни делал. Именно тогда я решил использовать OxyPlot, который пока доставляет мне немало головной боли.

Вот мой исходный вопрос! что я спросил в CodePlex. Кажется, мне там особо не помогают, поэтому я пытаюсь снова здесь.

У меня вопрос:

Кто-нибудь знает, как нанести НЕСКОЛЬКО LineSeries на участок ??

Мой подход до сих пор:

Я беру массив 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);

    }

Мой код работает, когда я в первый раз нажимаю кнопку «Данные графика», но при последующих попытках не работает со следующей ошибкой:

Элемент не может быть добавлен, он уже принадлежит к модели участка

Следующий график - это тип графика, который я хотел бы создать (он отлично работал с элементом управления WinForms Chart):

Изображение

Я хочу, чтобы при каждом запуске метода отображалась новая линия с новым цветом.


person Hooplator15    schedule 24.07.2014    source источник
comment
возможный дубликат привязки нескольких строк в OxyPlot   -  person Paul Zahra    schedule 24.07.2014
comment
Это не точная копия, так как мой подход немного отличался. Я не использовал привязку данных, но, вероятно, должен был бы использовать, поэтому я также рассмотрю этот подход.   -  person Hooplator15    schedule 24.07.2014


Ответы (3)


Вот как я раньше создавал несколько линий на диаграмме OxyPlot, ключевым моментом является создание набора точек данных для каждой серии - в следующем примере кода они называются 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);
person AwkwardCoder    schedule 24.07.2014
comment
Спасибо, как только я вернусь к своей рабочей станции, я посмотрю поближе и попробую. Я знал, что мне что-то не хватает. Спасибо за помощь! - person Hooplator15; 24.07.2014

Успеха !!!!

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 var series я добавлял исходную серию, которая уже была добавлена, а НЕ следующую серию var в списке! (тупой!)
  2. Я создавал новую модель каждый раз, когда запускал метод. Это означает, что каждый раз при запуске кода я добавлял серию, которая уже существовала в предыдущей модели. (тоже тупой!)
  3. Я каждый раз создавал новый сюжет и пытался добавить в новый сюжет модель, которая уже принадлежала предыдущему сюжету. (становится тупее ..)
  4. График добавлялся в сетку каждый раз, когда я запускал метод, поэтому мне пришлось сначала ОЧИСТИТЬ дочерние элементы сетки, прежде чем повторно добавлять тот же график.
  5. Я не обновлял сюжет.

Было много ошибок, но я справился с этим. Надеюсь, это поможет кому-то в будущем. Кроме того, я знаю, что не использую обычные методы привязки данных, но это, по крайней мере, работает.

Конечный результат:  рабочий участок

person Hooplator15    schedule 24.07.2014

Вот как можно добиться аналогичного результата в XAML, особенно если вы используете подход MVVM.

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>
person Bloggrammer    schedule 10.03.2020
comment
Но как это сделать динамически, то есть что, если вы не знаете количество ‹oxy: LineSeries› во время разработки? Мне нужно добавить LineSeries в ‹oxy: Plot.Series› во время выполнения .... - person Erik; 23.07.2020
comment
Вы можете программно создать LineSeries в программном коде. - person Bloggrammer; 01.11.2020