错误 此 PlotModel 已被 OxyPlot 图表中的某些其他 PlotView 控件使用

2024-05-03

我正在使用 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 重新创建视图时,都会生成一个新模型 也被重新创建。


See github ToolmakerSteve / 仓库 OxyplotApp1 https://github.com/ToolmakerSteve/OxyplotApp1,对于工作版本。


“此 PlotModel 已被其他一些 PlotView 控件使用”

经过对iOS的各种测试,我得出的结论是,在iOS上使用(CollectionView或ListView)+ Expander + Oxyplot从根本上来说是不可靠的。

Oxyplot 似乎使已知问题变得更糟扩展器和 CollectionView https://github.com/xamarin/XamarinCommunityToolkit/issues/1283.

因此,最重要的修复方法是停止使用这些集合视图。替换使用CollectionView with:

<StackLayout Spacing="0" BindableLayout.ItemsSource="{Binding KidModels}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>

为了获得更好的性能,请进行此更改,以便仅在用户第一次单击给定项目时创建每个图表:

void Expander_Tapped(System.Object sender, System.EventArgs e)
{
    // --- ADD THESE LINES ---
    if (ReferenceEquals(sender, expander)) {
        // User is tapping the existing expander. Don't do anything special.
        return;
    }
    ...
}

注意:还修复了如果用户连续点击扩展器三次则立即再次关闭的问题。


第一次单击每个扩展器时显示速度更快。这里有三种选择。从最快到最慢。使用第一个,但如果出现空白图表或其他问题,请切换到第二个。如果第二个仍然有问题,请切换到第三个 - 这是原始的,但时间延迟稍短:

if (item.Chart == null) {
    PlotModel model = CreateReportChart(item);
    Action action = () => {
        item.Chart = model;
    };
    if (false) {
        action();
    } else if (true) {
        Device.BeginInvokeOnMainThread(() => {
            action();
        });
    } else {
        Device.StartTimer(TimeSpan.FromSeconds(0.5), () => {
            action();

            return false;
        });
    }
}

可选:确保与 Oxyplot 一起使用时扩展器动画不会导致问题。

如果出现问题,但只是“有时”,请尝试此操作,看看情况是否有所改善:

<xct:Expander AnimationLength="0" ...>

这应该删除动画。


您可以删除诸如if (_chart.PlotView == null && value.PlotView == null)来自您的 OnPropertyChanged 相关代码。也就是说,始终执行 OnPropertyChanged。

原因:将来您可能希望生成修改后的绘图,因为数据已更改,并且您进行的测试将阻止 UI 看到更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

错误 此 PlotModel 已被 OxyPlot 图表中的某些其他 PlotView 控件使用 的相关文章

随机推荐

  • 音频端播放新文件

    我有一个webapp https radio repjesus com当您使用 ajax jquery 单击链接时加载并播放音轨 一切正常 但当曲目结束时 曲目将设置为循环 并且这种情况可以永远持续下去 我希望播放器从数据库中自动加载随机曲
  • 撤消 git merge(尚未推送)

    我只是将一些更改提交到我的功能分支之一 feedback tab 然后签出 master 并将它们合并到那里 我实际上打算将它们合并到我的 开发 分支中 现在 master 领先于 origin master 其远程 17 个提交 我还没有
  • git commit 给出错误:空提交集已通过

    当尝试恢复到以前的提交时 我尝试了 git revert no commit 0766c053 HEAD 然而这给出了一个错误 empty commit set passed 问题 该错误是什么意思 以及出了什么问题revert命令 删除
  • app_offline.htm 文件不起作用

    我已经为此奋斗了很多年 但我就是无法让它发挥作用 我去过的每个博客 网站都说您无需在 IIS 中执行任何操作 但这并不正确 因为有多个网站配置 例如应用程序 虚拟目录 简单的 php asp 网站 虚拟网站 有人可以向我解释一下 IIS7
  • 是否可以从 Visual Studio Online (VS Team Services) 编辑我的代码?

    I have 视觉工作室在线 http www visualstudio com products visual studio online overview vs 现在是 VS Team Services 帐户作为我的 MSDN 订阅的一
  • 如何在 Perl 中访问名称包含在变量中的常量?

    我有一组用 Perl 声明的常量 use constant C1 gt 111 use constant C2 gt 222 use constant C9 gt 999 my which constant C2 我如何构造一个 Perl
  • WiX - 根据环境将编译后的 web.config 复制到网站根目录

    作为 WiX 安装的一部分 我将所有转换 编译的 web config 文件复制到安装目录 编译后的 web config 的名称格式为 web ENV config 在我的安装 UI 中 我创建了一个自定义对话框 在其中解析 ENV 并填
  • Bash 变量:区分大小写?

    Bash shell 脚本区分大小写吗 是可变的date与DATE 是的 它区分大小写 就像 UNIX 的其余部分一样 date and DATE是两个不同的变量 makefile and Makefile是两个不同的文件 h and H是
  • 前导点的自动完成功能无法快速工作

    当我尝试在 swift 中使用 前导点语法 时 我没有得到任何自动完成建议 是否没有实现此自动完成功能 或者是我的 Xcode 版本 6 3 1 有问题 例如 当我尝试这样的事情时 let col UIColor whiteColor 在我
  • 数据操作 startdate enddate python pandas

    我有一个促销描述数据集 其中包含有关正在运行的各种促销活动及其开始日期 结束日期的信息 promo item start date end date Buy1 get 1 A 2015 01 08 2015 01 12 Buy1 get 1
  • 打印一个字符串,并将其特殊字符打印为文字转义序列

    我在 shell bash 脚本中有一个字符串 我想打印字符串 并将其所有 特殊字符 例如换行符 制表符等 打印为文字转义序列 例如换行符打印为 n 选项卡打印为 t 等等 不确定我是否使用了正确的术语 该示例应该能够澄清问题 Exampl
  • Enthought Python 中的线程 FFT

    Numpy SciPy 中的快速傅立叶变换 FFT 不是线程化的 Enthought Python 附带 Intel MKL 数值库 该库能够进行线程 FFT 如何获得这些例程 以下代码适用于 Windows 7 Ultimate 64 位
  • Cloud Run 是否支持服务器发送事件 (SSE)?

    我们无法让 SSE 从 Google Cloud Run 上的容器发送 我尝试过仅使用一个简单的 SSE 示例来托管容器 https github com kljensen node sse example https github com
  • debugger-ruby_core_source gem 没有提供 ruby​​-2.0.0-p451 的源代码

    我在其他 SO 问题中看到了非常类似的问题 例如debugger ruby core source gem 没有提供 ruby 1 9 2 p321 的源代码 https stackoverflow com questions 204618
  • AVFoundation 在后台/锁屏上播放音频 Swift

    我正在尝试找到一种使用 AVFoundation 在用户处于锁定屏幕上或在使用我的应用程序期间锁定应用程序时播放音频的方法 class ViewController UIViewController AVAudioPlayerDelegat
  • 如何在 Presto 中删除重复数据

    我有一个 Presto 表 假设它有 id name update time 列和数据 1 Amy 2018 08 01 1 Amy 2018 08 02 1 Amyyyyyyy 2018 08 03 2 Bob 2018 08 01 现在
  • 如何通过ajax点击时从javascript文件执行节点(控制台)命令

    我是 Node js 新手 这是我的问题 例如 我得到了 Web 应用程序 并且从该应用程序中我有一个按钮 单击按钮后我想运行节点控制台命令 例如 node socket io So button on click function run
  • 如果在 React JS 中选中复选框,如何隐藏或显示 div

    我如何在React JS中根据复选框状态 选中 未选中 显示 隐藏div 我对React很陌生 我知道如何在jquery中执行此操作 但在React上是另一种方法 提前致谢 EDITED 如果选中或未选中该复选框 则想要显示 隐藏带有 cl
  • F# 参数传递

    我一直认为 F 有两种不同的方式来传递参数 柯里化风格和元组风格 这实际上是正确的吗 是不是很简单一种风格 柯里化风格和参数可以是简单值或元组 e g someFunc a b 这不是一个函数吗one咖喱风格的参数恰好是一个元组 因此允许我
  • 错误 此 PlotModel 已被 OxyPlot 图表中的某些其他 PlotView 控件使用

    我正在使用 Xamarin Forms OxyPlot 图表 我有一个 CollectionView 每个 CollectionView 项都有一个扩展器 每个扩展器内部都有一个 PlotView