Xamarin.Forms:使用 OxyPlot 创建图表时出错
Xamarin.Forms: Error in creating a Chart using OxyPlot
大家好。我正在创建一个 Xamarin.Forms(便携式)应用程序,我想使用 OxyPlot 创建一个图表。我试过这段代码,但它有一个指向我的错误
LoadApplication(new App()); MainActivity.cs 在我的 Xamarin.Android 部分说明
"System.NullReferenceException: Object Reference not set to an Instance of an Object"
您认为这背后的原因是什么?
这些是我的一些代码:
SalesPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsDemo.Views.SalesPage"
xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms"
BackgroundImage="bg3.jpg"
Title="Sales Page">
<StackLayout>
<oxy:PlotView Model="{Binding OxyPlotModel}" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
SalesPage.xaml
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace XamarinFormsDemo.Views
{
public partial class SalesPage
{
public SalesPage()
{
InitializeComponent();
var plotModel = new PlotModel { Title = "OxyPlot Demo" };
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Maximum = 10, Minimum = 0 });
var series1 = new LineSeries
{
MarkerType = OxyPlot.MarkerType.Circle,
MarkerSize = 4,
MarkerStroke = OxyPlot.OxyColors.White
};
series1.Points.Add(new DataPoint(0.0, 6.0));
series1.Points.Add(new DataPoint(1.4, 2.1));
series1.Points.Add(new DataPoint(2.0, 4.2));
series1.Points.Add(new DataPoint(3.3, 2.3));
series1.Points.Add(new DataPoint(4.7, 7.4));
series1.Points.Add(new DataPoint(6.0, 6.2));
series1.Points.Add(new DataPoint(8.9, 8.9));
plotModel.Series.Add(series1);
}
}
}
MainActivity.cs
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using ImageCircle.Forms.Plugin.Droid;
namespace XamarinFormsDemo.Droid
{
[Activity(Label = "XamarinFormsDemo", Icon = "@drawable/recordsicon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();
ImageCircleRenderer.Init();
}
}
}
您没有在任何地方为页面设置 DataContext。至少不在您显示的代码中。因此,绑定到 OxyPlotModel
属性 似乎也不存在,将不起作用。
如果您只是为了查看您在页面中制作的模型而想要快速而肮脏的修复,那么只需将其分配给 PlotView
,如下所示:
- 为您的绘图视图添加名称属性。
x:Name="Graph"
- 只需将创建的 PlotModel 分配给
Graph
的模型 属性:Graph.Model = plotModel
.
但是,您可能需要在 OnAppearing
覆盖中执行此操作,因此您的代码可能需要在该方法中向下移动,例如:
public override void OnAppearing()
{
var plotModel = new PlotModel { Title = "OxyPlot Demo" };
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Maximum = 10, Minimum = 0 });
var series1 = new LineSeries
{
MarkerType = OxyPlot.MarkerType.Circle,
MarkerSize = 4,
MarkerStroke = OxyPlot.OxyColors.White
};
series1.Points.Add(new DataPoint(0.0, 6.0));
series1.Points.Add(new DataPoint(1.4, 2.1));
series1.Points.Add(new DataPoint(2.0, 4.2));
series1.Points.Add(new DataPoint(3.3, 2.3));
series1.Points.Add(new DataPoint(4.7, 7.4));
series1.Points.Add(new DataPoint(6.0, 6.2));
series1.Points.Add(new DataPoint(8.9, 8.9));
plotModel.Series.Add(series1);
Graph.Model = plotModel;
}
一个更好的方法是利用 MVVM 模式,通过创建一个 ViewModel,如下所示:
public class SalesViewModel : INotifyPropertyChanged
{
private PlotModel _plotModel;
public PlotModel PlotModel
{
get { return _plotModel; }
set {
_plotModel = value;
RaisePropertyChanged();
}
}
// other methods here that create your model
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler (this, new PropertyChangedEventArgs (propertyName));
}
}
然后您可以在某个地方实例化您的 ViewModel,可能在 OnAppearing() 中并将其设置为 BindingContext:
public override void OnAppearing()
{
var viewModel = new SalesViewModel();
this.BindingContext = viewModel;
}
然后您可以使用您在主页中创建的绑定:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsDemo.Views.SalesPage"
xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms"
BackgroundImage="bg3.jpg"
Title="Sales Page">
<StackLayout>
<oxy:PlotView Model="{Binding PlotModel}" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
记得每次更改 PlotModel
时调用 RaisePropertyChanged()
以使其反映在视图中:RaisePropertyChanged("PlotModel");
大家好。我正在创建一个 Xamarin.Forms(便携式)应用程序,我想使用 OxyPlot 创建一个图表。我试过这段代码,但它有一个指向我的错误 LoadApplication(new App()); MainActivity.cs 在我的 Xamarin.Android 部分说明
"System.NullReferenceException: Object Reference not set to an Instance of an Object"
您认为这背后的原因是什么?
这些是我的一些代码:
SalesPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsDemo.Views.SalesPage"
xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms"
BackgroundImage="bg3.jpg"
Title="Sales Page">
<StackLayout>
<oxy:PlotView Model="{Binding OxyPlotModel}" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
SalesPage.xaml
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace XamarinFormsDemo.Views
{
public partial class SalesPage
{
public SalesPage()
{
InitializeComponent();
var plotModel = new PlotModel { Title = "OxyPlot Demo" };
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Maximum = 10, Minimum = 0 });
var series1 = new LineSeries
{
MarkerType = OxyPlot.MarkerType.Circle,
MarkerSize = 4,
MarkerStroke = OxyPlot.OxyColors.White
};
series1.Points.Add(new DataPoint(0.0, 6.0));
series1.Points.Add(new DataPoint(1.4, 2.1));
series1.Points.Add(new DataPoint(2.0, 4.2));
series1.Points.Add(new DataPoint(3.3, 2.3));
series1.Points.Add(new DataPoint(4.7, 7.4));
series1.Points.Add(new DataPoint(6.0, 6.2));
series1.Points.Add(new DataPoint(8.9, 8.9));
plotModel.Series.Add(series1);
}
}
}
MainActivity.cs
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using ImageCircle.Forms.Plugin.Droid;
namespace XamarinFormsDemo.Droid
{
[Activity(Label = "XamarinFormsDemo", Icon = "@drawable/recordsicon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
OxyPlot.Xamarin.Forms.Platform.Android.PlotViewRenderer.Init();
ImageCircleRenderer.Init();
}
}
}
您没有在任何地方为页面设置 DataContext。至少不在您显示的代码中。因此,绑定到 OxyPlotModel
属性 似乎也不存在,将不起作用。
如果您只是为了查看您在页面中制作的模型而想要快速而肮脏的修复,那么只需将其分配给 PlotView
,如下所示:
- 为您的绘图视图添加名称属性。
x:Name="Graph"
- 只需将创建的 PlotModel 分配给
Graph
的模型 属性:Graph.Model = plotModel
.
但是,您可能需要在 OnAppearing
覆盖中执行此操作,因此您的代码可能需要在该方法中向下移动,例如:
public override void OnAppearing()
{
var plotModel = new PlotModel { Title = "OxyPlot Demo" };
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Maximum = 10, Minimum = 0 });
var series1 = new LineSeries
{
MarkerType = OxyPlot.MarkerType.Circle,
MarkerSize = 4,
MarkerStroke = OxyPlot.OxyColors.White
};
series1.Points.Add(new DataPoint(0.0, 6.0));
series1.Points.Add(new DataPoint(1.4, 2.1));
series1.Points.Add(new DataPoint(2.0, 4.2));
series1.Points.Add(new DataPoint(3.3, 2.3));
series1.Points.Add(new DataPoint(4.7, 7.4));
series1.Points.Add(new DataPoint(6.0, 6.2));
series1.Points.Add(new DataPoint(8.9, 8.9));
plotModel.Series.Add(series1);
Graph.Model = plotModel;
}
一个更好的方法是利用 MVVM 模式,通过创建一个 ViewModel,如下所示:
public class SalesViewModel : INotifyPropertyChanged
{
private PlotModel _plotModel;
public PlotModel PlotModel
{
get { return _plotModel; }
set {
_plotModel = value;
RaisePropertyChanged();
}
}
// other methods here that create your model
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler (this, new PropertyChangedEventArgs (propertyName));
}
}
然后您可以在某个地方实例化您的 ViewModel,可能在 OnAppearing() 中并将其设置为 BindingContext:
public override void OnAppearing()
{
var viewModel = new SalesViewModel();
this.BindingContext = viewModel;
}
然后您可以使用您在主页中创建的绑定:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsDemo.Views.SalesPage"
xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms"
BackgroundImage="bg3.jpg"
Title="Sales Page">
<StackLayout>
<oxy:PlotView Model="{Binding PlotModel}" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
记得每次更改 PlotModel
时调用 RaisePropertyChanged()
以使其反映在视图中:RaisePropertyChanged("PlotModel");