Search code examples
androidxamarinxamarin.androidmvvmcrossoxyplot

Binding OxyPlot via MVVMCross in Xamarin.Android


I have added OxyPlot Android and Core in my Xamarin PCL based project where I am using MVVMCross.

I have added the plotview in my xml as follows. But I do not know how to bind this view using MVVMCross.

Is there any good example or resources to follow?

MyView.xml

<oxyplot.xamarin.android.PlotView
android:id="@+id/plot"
android:layout_width="match_parent"
android:layout_height="match_parent" /> 

MyView.cs

public class MyView : MvxFragment<MyViewModel>
{
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignored = base.OnCreateView(inflater, container, savedInstanceState);
        var view = this.BindingInflate(Resource.Layout.MyView, null)

        MyViewModel MyMainViewModel = new MyViewModel();
        var a = view.FindViewById<PlotView>(Resource.Id.plot);
        a.Model = MyViewModel.MyModel;

        return view;
    }
}

MyViewModel.cs

public PlotModel MyModel { get; set; }
public MyViewModel
{
  PlotModel mo = new PlotModel();
  var s1 = new LineSeries()
  {
    Color = OxyColors.SkyBlue,
    MarkerType = MarkerType.Circle,
    MarkerSize = 6,
    MarkerStroke = OxyColors.White,
    MarkerFill = OxyColors.SkyBlue,
    MarkerStrokeThickness = 1.5
  };
  s1.Points.Add(new DataPoint(0, 10));
  s1.Points.Add(new DataPoint(10, 40));
  s1.Points.Add(new DataPoint(40, 20));
  s1.Points.Add(new DataPoint(60, 30));
  mo.Series.Add(s1);
  MyModel = mo;
}

Additional Information for OxyPlot installation

I have added OxyPlot as follows through Package Console.

In the PCL

PM> Install-Package OxyPlot.Core -Version 1.0.0-unstable1983 -Pre

In the Android

PM> Install-Package OxyPlot.Xamarin.Android -Pre

Or you can also add them in Nuget Console from prelease library.


Solution

  • You should be able to achieve what you want using standard Mvx property binding. No custom binding required.

    Example based on question:

    Approach 1: Fluent binding

    ViewModel

    public class MyViewModel : MvxViewModel
    {
        public MyViewModel()
        {
            GeneratePlotPoints();
        }
    
        void GeneratePlotPoints()
        {
            var mo = new PlotModel();
            var s1 = new LineSeries()
            {
                Color = OxyColors.SkyBlue,
                MarkerType = MarkerType.Circle,
                MarkerSize = 6,
                MarkerStroke = OxyColors.White,
                MarkerFill = OxyColors.SkyBlue,
                MarkerStrokeThickness = 1.5
            };
            s1.Points.Add(new DataPoint(0, 10));
            s1.Points.Add(new DataPoint(10, 40));
            s1.Points.Add(new DataPoint(40, 20));
            s1.Points.Add(new DataPoint(60, 30));
            mo.Series.Add(s1);
            MyModel = mo;
        }
    
        PlotModel _myModel;
        public PlotModel MyModel
        {
            get { return _myModel; }
            set { SetProperty(ref _myModel, value); }
        }
    }
    

    View/Layout

    <oxyplot.xamarin.android.PlotView
       android:id="@+id/plot"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />
    

    Fragment/Code Behind

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignored = base.OnCreateView(inflater, container, savedInstanceState);
        var view = this.BindingInflate(Resource.Layout.MyView, null);
    
        var graphControl = view.FindViewById<PlotView>(Resource.Id.plot);
    
        var bindset = this.CreateBindingSet<MyView, MyViewModel>();
        bindset.Bind(graphControl).For(c => c.Model).To(vm => vm.MyModel);
        bindset.Apply();
    
        return view;
    }
    

    Approach 2: Xml Binding

    ViewModel

    Same as above

    View/Layout

    <oxyplot.xamarin.android.PlotView
       android:id="@+id/plot"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       local:MvxBind="Model MyModel"/>
    

    Fragment/ Code behind

    No binding code needed, just make sure to run the layout through the binding inflater.

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignored = base.OnCreateView(inflater, container, savedInstanceState);
        return this.BindingInflate(Resource.Layout.MyView, null);
    }