Search code examples
c#xamlxamarinchartsoxyplot

Stacked Column Chart Using Oxyplot and Xamarin


I've been using OxyPlot in my Xamarin.ios And Xamarin.Android projects to plot columns charts.This is how I've drawn the column chart using oxyplot.

Now I need a stacked column chart. I could't find it in the documentation. Is it possible with oxyplot? How? Any help is appreciated..

public class MeasurementGraph 
{

    public PlotModel VitalModel { get; set; }
    public VitalGraph graph { get; set; }

    public MeasurementGraph (VitalGraph graph)
    {
        this.graph = graph;
        var model = new PlotModel { Title = "" };
        model.PlotAreaBorderColor = OxyColors.Transparent;

        model.Axes.Add (GetXAxis ());
        model.Axes.Add (GetYAxis ());
        model.Series.Add (GetValueSeries ());

        if (Math.Abs (graph.trendStart) > float.Epsilon && Math.Abs (graph.trendEnd) > float.Epsilon)
            model.Series.Add (GetXtraSeries ());
            VitalModel = model;
        }

    CategoryAxis GetXAxis ()
    {
        int fontSize;
        if (Math.Abs (graph.trendStart) > float.Epsilon)
            fontSize = 6;
        else
            fontSize = 8;
        CategoryAxis categoryAxis = new CategoryAxis () {
            Position = AxisPosition.Bottom,
            MinorTickSize = 0,
            MajorTickSize = 0,
            MajorGridlineStyle = LineStyle.None,
            MinorGridlineStyle = LineStyle.None,
            FontSize = fontSize,
            IsPanEnabled = false,
            IsZoomEnabled = false,
        };

        foreach (string day in graph.dayList)
            categoryAxis.ActualLabels.Add (day);
        return categoryAxis;
    }

    LinearAxis GetYAxis ()
    {
        List<float> valueList = graph.valueList.Select (x => float.Parse (x)).ToList ();
        float maxValue = valueList.Max ();

        float minValue = valueList.Max ();


            return new LinearAxis () {
                AxislineStyle = LineStyle.None,
                Position = AxisPosition.Left,
                MinorTickSize = 0,
                MajorTickSize = 0,
                MajorGridlineStyle = LineStyle.Solid,
                MajorGridlineColor = OxyColor.Parse ("#f5f5f5"),
                MinorGridlineStyle = LineStyle.None,
                Maximum = maxValue,
                Minimum = minValue,
                FontSize = 8,
                MajorStep = (maxValue - minValue) / 4,
                IsPanEnabled = false,
                IsZoomEnabled = false

            };
        }

        ColumnSeries GetValueSeries ()
        {
            var series = new ColumnSeries ();
            series.ColumnWidth = 50;
            for (int i = 0; i < graph.valueList.Count; i++) {
                series.Items.Add (new ColumnItem {
                    Value = double.Parse (graph.valueList [i]),
                    Color = OxyColor.Parse (graph.colorList [i])
                });
            }
            return series;
        }

        LineSeries GetXtraSeries ()
        {
            var series = new LineSeries {
                StrokeThickness = 2,
                MarkerType = MarkerType.None,
                MarkerSize = 4,
                MarkerStroke = OxyColors.White,
                MarkerStrokeThickness = 2,
                Color = OxyColors.Blue
            };
            int xStart = graph.vitalId == 20 ? 0 : -1;
            int xEnd = graph.vitalId == 20 ? graph.valueList.Count - 1 : graph.valueList.Count;

            series.Points.Add (new DataPoint (xStart, graph.trendStart));
            series.Points.Add (new DataPoint (xEnd, graph.trendEnd));
            return series;
        }
    }

Solution

  • This is adapted from one of their samples:

    MainPage:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:oxy="clr-namespace:OxyPlot.Xamarin.Forms;assembly=OxyPlot.Xamarin.Forms"
                 xmlns:local="clr-namespace:App48"
                 x:Class="App48.MainPage">
    
      <ContentPage.BindingContext>
        <local:MyViewModel/>
      </ContentPage.BindingContext>
    
      <oxy:PlotView Model="{Binding Model}"></oxy:PlotView>
    
    </ContentPage>
    

    ViewModel:

    public class MyViewModel
    {
        public PlotModel Model { get; set; }
    
        public MyViewModel()
        {
            Model = new PlotModel();
            Model.LegendBorderThickness = 0;
            Model.LegendOrientation = LegendOrientation.Horizontal;
            Model.LegendPlacement = LegendPlacement.Outside;
            Model.LegendPosition = LegendPosition.BottomCenter;
            Model.Title = "Simple stacked model";
            var categoryAxis1 = new CategoryAxis();
            categoryAxis1.MinorStep = 1;
            categoryAxis1.Labels.Add("Category A");
            categoryAxis1.Labels.Add("Category B");
            categoryAxis1.Labels.Add("Category C");
            categoryAxis1.Labels.Add("Category D");
            Model.Axes.Add(categoryAxis1);
            var linearAxis1 = new LinearAxis();
            linearAxis1.AbsoluteMinimum = 0;
            linearAxis1.MaximumPadding = 0.06;
            linearAxis1.MinimumPadding = 0;
            Model.Axes.Add(linearAxis1);
            var columnSeries1 = new ColumnSeries();
            columnSeries1.IsStacked = true;
            columnSeries1.StrokeThickness = 1;
            columnSeries1.Title = "Series 1";
            columnSeries1.Items.Add(new ColumnItem(25));
            columnSeries1.Items.Add(new ColumnItem(137));
            columnSeries1.Items.Add(new ColumnItem(18));
            columnSeries1.Items.Add(new ColumnItem(40));
            Model.Series.Add(columnSeries1);
            var columnSeries2 = new ColumnSeries();
            columnSeries2.IsStacked = true;
            columnSeries2.StrokeThickness = 1;
            columnSeries2.Title = "Series 2";
            columnSeries2.Items.Add(new ColumnItem(12));
            columnSeries2.Items.Add(new ColumnItem(14));
            columnSeries2.Items.Add(new ColumnItem(120));
            columnSeries2.Items.Add(new ColumnItem(26));
            Model.Series.Add(columnSeries2);
        }
    }
    

    enter image description here