我正在使用 Xamarin.Forms OxyPlot 图表。我有一个 CollectionView,每个 CollectionView 项都有一个扩展器,每个扩展器内部都有一个 PlotView
<CollectionView x:Name="Kids">
<CollectionView.ItemTemplate>
<DataTemplate>
<xct:Expander Tapped="Expander_Tapped" ClassId="{Binding rowNumber}">
<xct:Expander.Header>
<Frame Padding="0" CornerRadius="10" Margin="5" BackgroundColor="White" HasShadow="False">
<StackLayout>
<Grid BackgroundColor="#f8f8f8">
<StackLayout Padding="5" Orientation="Horizontal">
<Image x:Name="kidProfile" Source="{Binding image}" WidthRequest="75" HeightRequest="75" HorizontalOptions="Start" Aspect="AspectFill" />
<StackLayout Orientation="Vertical">
<Label Text="{Binding first_name}"></Label>
<StackLayout Orientation="Horizontal">
<Label Text="Grade: " FontSize="Small"></Label>
<Label Text="{Binding grade}" FontSize="Small"></Label>
</StackLayout>
</StackLayout>
</StackLayout>
<Image Margin="20" HorizontalOptions="End" Source="arrowDown.png" HeightRequest="15"></Image>
</Grid>
</StackLayout>
</Frame>
</xct:Expander.Header>
<oxy:PlotView Model="{Binding chart}" HeightRequest="200" WidthRequest="100" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
我在我的班级中分配了 PlotModel
public class ReportsClass
{
public PlotModel chart
{
get
{
PlotModel model = new PlotModel();
CategoryAxis xaxis = new CategoryAxis();
xaxis.Position = AxisPosition.Bottom;
xaxis.MajorGridlineStyle = LineStyle.None;
xaxis.MinorGridlineStyle = LineStyle.None;
xaxis.MinorTickSize = 0;
xaxis.MajorTickSize = 0;
xaxis.TextColor = OxyColors.Gray;
xaxis.FontSize = 10.0;
xaxis.Labels.Add("S");
xaxis.Labels.Add("M");
xaxis.Labels.Add("T");
xaxis.Labels.Add("W");
xaxis.Labels.Add("T");
xaxis.Labels.Add("F");
xaxis.Labels.Add("S");
xaxis.GapWidth = 10.0;
xaxis.IsPanEnabled = false;
xaxis.IsZoomEnabled = false;
LinearAxis yaxis = new LinearAxis();
yaxis.Position = AxisPosition.Left;
yaxis.MajorGridlineStyle = LineStyle.None;
xaxis.MinorGridlineStyle = LineStyle.None;
yaxis.MinorTickSize = 0;
yaxis.MajorTickSize = 0;
yaxis.TextColor = OxyColors.Gray;
yaxis.FontSize = 10.0;
yaxis.FontWeight = FontWeights.Bold;
yaxis.IsZoomEnabled = false;
yaxis.IsPanEnabled = false;
ColumnSeries s2 = new ColumnSeries();
s2.TextColor = OxyColors.White;
s2.Items.Add(new ColumnItem
{
Value = Sunday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Monday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Tuesday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Wednesday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Thursday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Friday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = Saturday,
Color = OxyColor.Parse("#02cc9d")
});
model.Axes.Add(xaxis);
model.Axes.Add(yaxis);
model.Series.Add(s2);
model.PlotAreaBorderColor = OxyColors.Transparent;
return model;
}
}
}
现在这可以工作,但是在 Expander 中,当我展开一个项目时,PlotView 根本不会显示。所以我改变了我的类以使用 INotifyPropertyChanged
public class ReportsClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public PlotModel chart
{
get => _chart;
set
{
_chart = value;
if(_chart.PlotView == null && value.PlotView == null)
{
OnPropertyChanged("chart");
}
}
}
public PlotModel _chart;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
if(this.chart.PlotView == null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在我后面的代码中,我使用扩展器的点击方法来填充 PlotView:
void Expander_Tapped(System.Object sender, System.EventArgs e)
{
if(expander != null)
{
expander.IsExpanded = false;
}
expander = sender as Expander;
int id = Convert.ToInt32(expander.ClassId);
ReportsClass item = newKidList[id];
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
if (item.chart == null)
{
PlotModel model = new PlotModel();
CategoryAxis xaxis = new CategoryAxis();
xaxis.Position = AxisPosition.Bottom;
xaxis.MajorGridlineStyle = LineStyle.None;
xaxis.MinorGridlineStyle = LineStyle.None;
xaxis.MinorTickSize = 0;
xaxis.MajorTickSize = 0;
xaxis.TextColor = OxyColors.Gray;
xaxis.FontSize = 10.0;
xaxis.Labels.Add("S");
xaxis.Labels.Add("M");
xaxis.Labels.Add("T");
xaxis.Labels.Add("W");
xaxis.Labels.Add("T");
xaxis.Labels.Add("F");
xaxis.Labels.Add("S");
xaxis.GapWidth = 10.0;
xaxis.IsPanEnabled = false;
xaxis.IsZoomEnabled = false;
LinearAxis yaxis = new LinearAxis();
yaxis.Position = AxisPosition.Left;
yaxis.MajorGridlineStyle = LineStyle.None;
xaxis.MinorGridlineStyle = LineStyle.None;
yaxis.MinorTickSize = 0;
yaxis.MajorTickSize = 0;
yaxis.TextColor = OxyColors.Gray;
yaxis.FontSize = 10.0;
yaxis.FontWeight = FontWeights.Bold;
yaxis.IsZoomEnabled = false;
yaxis.IsPanEnabled = false;
ColumnSeries s2 = new ColumnSeries();
s2.TextColor = OxyColors.White;
s2.Items.Add(new ColumnItem
{
Value = item.Sunday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Monday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Tuesday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Wednesday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Thursday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Friday,
Color = OxyColor.Parse("#02cc9d")
});
s2.Items.Add(new ColumnItem
{
Value = item.Saturday,
Color = OxyColor.Parse("#02cc9d")
});
model.Axes.Add(xaxis);
model.Axes.Add(yaxis);
model.Series.Add(s2);
model.PlotAreaBorderColor = OxyColors.Transparent;
item.chart = model;
}
return false;
});
}
然而,最终我会得到这个错误:
此 PlotModel 已被其他一些 PlotView 控件使用
现在我明白 PlotView 和它的 PlotModel 之间存在一对一的关系,这给了我们错误,所以我尝试检查 PlotModel 是否有 PlotView,但我仍然收到此错误。
我找到了这个解决方案:
如果您将 OxyPlot 的父视图设置为 DataTemplate
每次都会创建一个新的 OxyPlot,然后 OxyPlot 无法缓存。 A
每次都会创建新的 PlotModel 和 PlotView,此错误是
避免(至少这似乎对我有用,我正在使用 CarouselView)
https://github.com/oxyplot/oxyplot-xamarin/issues/17 https://github.com/oxyplot/oxyplot-xamarin/issues/17
但我不知道如何为集合视图执行此操作,任何帮助将不胜感激。
我还发现了这个:
这是 OxyPlot 在 MVVM 中使用时非常常见的问题。在
OxyPlot,视图和模型是1对1映射的,当第二个视图
正在尝试绑定相同的 PlotModel,您会遇到“PlotModel
已被其他一些 PlotView 控件使用”。在 iOS 上,ListView 的
单元格在滚动时将被重新创建。在这种情况下,将会有
是一个新创建的视图试图绑定相同的 PlotModel,然后
你有这个问题。在Android上,我想你也会遇到同样的问题
也。尝试将手机从横向改为纵向,看看是否有
同样的问题。在Android中,视图将被完全重新创建
当方向改变时。
一个快速修复方法是稍微破坏一下 MVVM 设计。不
在单独的位置创建模型,但在
看法。因此,每当 iOS 或 Android 重新创建视图时,都会生成一个新模型
也被重新创建。
https://github.com/oxyplot/oxyplot-xamarin/issues/60 https://github.com/oxyplot/oxyplot-xamarin/issues/60
但我不知道如何应用这部分:
一个快速修复方法是稍微破坏一下 MVVM 设计。不
在单独的位置创建模型,但在
看法。因此,每当 iOS 或 Android 重新创建视图时,都会生成一个新模型
也被重新创建。