Using OxyPlot with Xamarin Forms

Those who are working with Xamarin.Forms know that there is no out of box support for charts/graphs in Xamarin Forms. If you want to show any data report in the form of charts/graph like Pie, Bar etc you will have to use third party graph controls like Syncfusion (Some Xamarin pre-built examples use these), Infragistics or Telerik controls and you have to pay license fee for same.
There is an little known open source plotting library for Xamarin Forms called OxyPlot, this library is not only free/Open source, It’s also easy to use. However you may have to play around with code samples to understand the working of these graph controls. In this article we will learn how to use a few of graph options OxyPlot.

  1. As usual create a new Xamarin Forms XAML Project
  2. Add the Nuget Package named ‘OxyPlot.Xamarin.Forms’ to all your projects as shown in below Image
  3. Just like Xamarin Forms, Oxyplot also needs to be initialized in the platform specific projects so that it can work.
  4. Add following code in MainActivity.cs file of your Android project just After global::Xamarin.Forms.Forms.Init(this, bundle); line in onCreate method
    OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();
    
  5. Similarly Add following code in AppDelegate.cs file of your iOS project just After global::Xamarin.Forms.Forms.Init(); line in FinishedLaunching method
    OxyPlot.Xamarin.Forms.Platform.iOS.PlotViewRenderer.Init();
    
  6. And in the same way Add following code in App.xaml.cs file of your UWP project just After Xamarin.Forms.Forms.Init(e); line in FinishedLaunching method
    OxyPlot.Xamarin.Forms.Platform.UWP.PlotViewRenderer.Init();
    
  7. Once the Oxyplot component is initialized in all the platform projects of the application, we can use the component in same way as we use any user control in Xamarin Forms. For Example the following Code is of the File “PieEx.xaml” Where we are declaring the Oxyplot component with local namespace and the creating the control of same.
    <?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"
                 x:Class="OxyPlotEx.PieEx">
      <AbsoluteLayout>
        <oxy:PlotView Model="{Binding PieModel}" 
                      AbsoluteLayout.LayoutBounds="20,0,.9,.9"
                      AbsoluteLayout.LayoutFlags="WidthProportional,HeightProportional" />
      </AbsoluteLayout>
    </ContentPage>
    

    As you can see from the code that the PlotView control requires Model to show the data that’s why we have binded that property with PieModel which is object of type PlotModel avilable in OxyPlot Library.

  8. The ContentPage shown in previous step is binded with the object of following class, which has three properties named PieModel,AreaModel,BarModel,StackedBarModel all of type PlotModel as this same object is used to bind rest of 3 pages used in the example to show different types of graphs like Area, Stacked Bar and Normal Comparison Bar. These charts are created using hard coded values in the example however you can use similar code to show any data you get from Web service or database.

    public class OxyExData
        {
            public PlotModel PieModel { get; set; }
            public PlotModel AreaModel { get; set; }
            public PlotModel BarModel { get; set; }
            public PlotModel StackedBarModel { get; set; }
    
            public OxyExData()
            {
                PieModel = CreatePieChart();
                AreaModel = CreateAreaChart();
                StackedBarModel = CreateBarChart(true,"Stacked Bar");
                BarModel = CreateBarChart(false, "Un-Stacked Bar");
            }
            private PlotModel CreatePieChart()
            {
                var model = new PlotModel { Title = "World population by continent" };
    
                var ps = new PieSeries
                {      
                    StrokeThickness = .25,
                    InsideLabelPosition = .25,
                    AngleSpan = 360,
                    StartAngle = 0
                };
    
                // http://www.nationsonline.org/oneworld/world_population.htm
                // http://en.wikipedia.org/wiki/Continent
                ps.Slices.Add(new PieSlice("Africa", 1030) { IsExploded = false });
                ps.Slices.Add(new PieSlice("Americas", 929) { IsExploded = false });
                ps.Slices.Add(new PieSlice("Asia", 4157));
                ps.Slices.Add(new PieSlice("Europe", 739) { IsExploded = false });
                ps.Slices.Add(new PieSlice("Oceania", 35) { IsExploded = false });
                model.Series.Add(ps);
                return model;
            }
    
            public PlotModel CreateAreaChart()
            {
                var plotModel1 = new PlotModel { Title = "AreaSeries with crossing lines" };
                var areaSeries1 = new AreaSeries();
                areaSeries1.Points.Add(new DataPoint(0, 50));
                areaSeries1.Points.Add(new DataPoint(10, 140));
                areaSeries1.Points.Add(new DataPoint(20, 60));
                areaSeries1.Points2.Add(new DataPoint(0, 60));
                areaSeries1.Points2.Add(new DataPoint(5, 80));
                areaSeries1.Points2.Add(new DataPoint(20, 70));
                plotModel1.Series.Add(areaSeries1);
                return plotModel1;
            }
    
            private PlotModel CreateBarChart(bool stacked, string title)
            {
                var model = new PlotModel
                {
                    Title = title,
                    LegendPlacement = LegendPlacement.Outside,
                    LegendPosition = LegendPosition.BottomCenter,
                    LegendOrientation = LegendOrientation.Horizontal,
                    LegendBorderThickness = 0
                };
    
                var s1 = new BarSeries { Title = "Series 1", IsStacked = stacked, StrokeColor = OxyColors.Black, StrokeThickness = 1 };
                s1.Items.Add(new BarItem { Value = 25 });
                s1.Items.Add(new BarItem { Value = 137 });
                s1.Items.Add(new BarItem { Value = 18 });
                s1.Items.Add(new BarItem { Value = 40 });
    
                var s2 = new BarSeries { Title = "Series 2", IsStacked = stacked, StrokeColor = OxyColors.Black, StrokeThickness = 1 };
                s2.Items.Add(new BarItem { Value = 12 });
                s2.Items.Add(new BarItem { Value = 14 });
                s2.Items.Add(new BarItem { Value = 120 });
                s2.Items.Add(new BarItem { Value = 26 });
    
                var categoryAxis = new CategoryAxis { Position = CategoryAxisPosition() };
                categoryAxis.Labels.Add("Category A");
                categoryAxis.Labels.Add("Category B");
                categoryAxis.Labels.Add("Category C");
                categoryAxis.Labels.Add("Category D");
                var valueAxis = new LinearAxis { Position = ValueAxisPosition(), MinimumPadding = 0, MaximumPadding = 0.06, AbsoluteMinimum = 0 };
                model.Series.Add(s1);
                model.Series.Add(s2);
                model.Axes.Add(categoryAxis);
                model.Axes.Add(valueAxis);
                return model;
            }
    
            private AxisPosition CategoryAxisPosition()
            {
                if (typeof(BarSeries) == typeof(ColumnSeries))
                {
                    return AxisPosition.Bottom;
                }
    
                return AxisPosition.Left;
            }
    
            private AxisPosition ValueAxisPosition()
            {
                if (typeof(BarSeries) == typeof(ColumnSeries))
                {
                    return AxisPosition.Left;
                }
    
                return AxisPosition.Bottom;
            }
    
        }
    
  9. As you can see from the above example is that we can use same PlotModel type of object to show different types of data by adding different types of series object to it.
  10. The sample code given in this article are published on Github and it has 3 more screens showing Area Graph, Stacked Bar Graph and Comparison Bar Graph
  11. This is how the sample application looks like when executed in iOS simulator:

This article has just touched the surface of using Oxyplot controls to create different types of charts and graphs, you can experiment more with it by trying out their examples. Let me know if you need any particular graph example.

๐Ÿ™‚ ๐Ÿ™‚ Happy Coding ๐Ÿ™‚ ๐Ÿ™‚

7 Comments

  1. Have you managed to build an UWP release app with an OxyPlot that shows up? OxyPlot is great but that problem with Xamarin makes it still unstable to use. If someone could involve the .NET Native Compiler team I think they’d solve it!

  2. Hi, I need to display the Bar Chart Horizontally, let me know what changes need to be done for this examples.
    I mean categories on width axis and values on Height axis.

    And also I need to add this Bar graph as in a Listview Item right side area, not complete screen.

    Please let me know does it possible with this code.

2 Trackbacks / Pingbacks

  1. Dew Drop - January 30, 2017 (#2410) - Morning Dew
  2. Getting Started with SkiaSharp with Xamarin Forms – Error To Solutions

Leave a Reply

Your email address will not be published.


*