Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How to create a Dynamic Pie Chart in Xamarin.Forms?

Good Day Everyone. Does anyone know how can I make the content of my Pie Chart (OxyPLot) dynamic? Meaning the data should not be pre-defined but should come from my Database. I was able to retrieve data using Linq Expression and test it in WEB API. But I don't know how am I gonna use it to my Chart. Please help me regarding this. Thanks a lot :)

Answers

  • sunfishsunfish USMember ✭✭
    edited October 2016

    I've been doing that so maybe this helps:

    • In the .xaml file for the page, I bind the Model in the OxyPlot PlotView object to a public property of type PlotModel (say it's called DonutPlotModel) in the corresponding view model .cs file.
    • Remember to set the BindingContext of the content page corresponding to the .xaml to the view model
    • The View Controller should implement the INotifyPropertyChanged.
    • Every time you need to change the pie chart, instantiate a new PlotModel object and populate it with a PieSeries containing the desired data, and then set it to the DonutPlotModel property in the view model, and the pie chart will update (no need to call any refreshing methods)

    in .xaml:

                                <oxy:PlotView BackgroundColor="Transparent" 
                                              Model="{Binding DonutPlotModel}" 
                                              HeightRequest="120" WidthRequest="300" 
                                              HorizontalOptions="Center" VerticalOptions="Center" />
    

    where DonutPlotModel is an OxyPlot PlotModel object that is a property in this page's BindingContext view model.

  • sunfishsunfish USMember ✭✭

    After-thought: the same thing can be achieved using an IValueConverter. In this case, you bind the public property in the view model to the oxyplot plotview and pass in the converter object you wrote for your donut chart. The converter then takes the data object and 'convert' it to the chart. I find this approach less straight-forward than the one mentioned before because if you need to display different data based on user input (from a picker, say) and you want to tailor the axes labels/title to the data, you need to pass in a parameter to the IValueConverter to tell it which data set is expected, and I prefer to just switch out the PlotModel as needed.

    Let me know if this is too confusing to follow and I can post more example code / explain more...

  • EBatikEBatik NLMember ✭✭✭

    @sunfish hi ! i have the same question! im working with BarSeries from OxyPlot and i would like to update the graph each time the user selects a different value from a slider. Do you have any examples?

  • sunfishsunfish USMember ✭✭
    edited October 2016

    @EBatik Sorry for the wait - I wrote an example and hope this helps. Basically you bind an Oxyplot PlotModel object in your view model to the Model field of the PlotView on your ContentPage, and whenever the slider changes value, generate a new PlotModel in the slider value's setter. I'm sure there are more succinct ways of doing it. In my project I present downloaded data in charts, and the user can pick a set of data to view with a picker - in this case I store all the PlotModel the user can pick from in a dictionary, so they don't have to be drawn each time.

    In the content page xaml:

        <ContentPage.Content>
            <StackLayout Padding="20, 40, 20, 0">
            <Label Text="Slider 1" VerticalOptions="Center" HorizontalOptions="Center" />
            <Slider x:Name="Slider1" ValueChanged="onSliderValueChanged"
                    Minimum="0" Maximum="100" />
    
            <oxy:PlotView BackgroundColor="Transparent" Margin="10, 40, 10, 10"
                Model="{Binding CurrentPlotModel}"
                HeightRequest="300" WidthRequest="1000" />
    
        </StackLayout>
    
        </ContentPage.Content>
    

    In this xaml's code-behind:

    public partial class DynamicChartExamplePage : ContentPage
        {
            private ViewModel viewModel;
    
            public DynamicChartExamplePage()
            {
                InitializeComponent();
    
    
                this.BindingContext = new ViewModel();
    
                viewModel = (ViewModel)this.BindingContext;
            }
    
            private void onSliderValueChanged(object sender, EventArgs e)
            {
                Slider slider = (Slider)sender;
                viewModel.SliderVal = slider.Value;
            }
        }
    

    In your view model that controls this page:

        public class ViewModel : ObservableObject
        {
            public ViewModel()
            {
                sliderVal = 0;
    
                CurrentPlotModel = generatePlotModel();
            }
    
            private PlotModel currentPlotModel;
    
            public PlotModel CurrentPlotModel
            { 
                get { return currentPlotModel; }
                set { SetProperty(ref currentPlotModel, value); }
            }
    
            private double sliderVal;
    
            public double SliderVal
            { 
                get { return sliderVal; }
                set 
                { 
                    SetProperty(ref sliderVal, value);
                    CurrentPlotModel = generatePlotModel();
                }
            }
    
            private PlotModel generatePlotModel()
            { 
                var model = new PlotModel
                {
                    Title = "",
                    LegendPosition = LegendPosition.BottomCenter,
                    PlotAreaBorderColor = OxyColors.Transparent
                };
    
                var series = new BarSeries
                {
                    Title = "slider value",
                    StrokeThickness = 0,
                    FillColor = OxyColors.CornflowerBlue
                };
                series.Items.Add(new BarItem { Value = sliderVal });
    
                model.Axes.Add(new LinearAxis 
                { 
                    Position = AxisPosition.Bottom, 
                    Minimum = 0,
                    Maximum = 100
                } );
    
                model.Series.Add(series);
                return model;
            }
    
        }
    
    
  • EBatikEBatik NLMember ✭✭✭

    @sunfish
    Thank you so much for your time! Its a great example.

Sign In or Register to comment.