【问题标题】:Exception in ZXingBarcodeImageView when removing from ObservableCollection从 ObservableCollection 中删除时 ZXingBarcodeImageView 出现异常
【发布时间】:2016-06-07 07:56:38
【问题描述】:

我使用ObservableCollection<BarcodeInfo> 作为ItemsSource 的ListView 来生成ViewCells。一个 Cell 包含 2 个Labels 和一个ZXingBarcodeImageView,绑定到我的BarcodeInfo-class,一切都按预期工作。

现在我要从ListView 中删除几个单元格,但是一旦我尝试这样做,我就会从ZXingBarcodeImageView 中得到以下异常

System.ArgumentException: 发现空内容

这是我的 XAML

<ListView RowHeight="50">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="3*" />
                    </Grid.ColumnDefinitions>

                    <zxing:ZXingBarcodeImageView
                        BarcodeFormat="{Binding Format}"
                        BarcodeOptions="{Binding Options}"
                        BarcodeValue="{Binding Text}"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        Margin="5"
                        Grid.Column="0"/>

                    <StackLayout  Grid.Row="0" Grid.Column="1"
                              Spacing="0" VerticalOptions="CenterAndExpand">
                        <Label Text="{Binding Text}"
                             LineBreakMode="TailTruncation"
                             VerticalOptions="End"/>
                        <Label Text="{Binding Format}"
                             VerticalOptions="End"
                             LineBreakMode="TailTruncation"/>
                    </StackLayout>
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ListView 中ObservableCollection&lt;BarcodeInfo&gt; _barcodeCollection; 的类

public class BarcodeInfo
{
    public string Text
    { get; set; }

    public string Detail
    { get; set; }

    public BarcodeFormat Format
    { get; set; }

    public EncodingOptions Options
    { get; set; }
}

我一尝试异常就会发生

_barcodeCollection.RemoveAt(i);

我已经实现了INotifyPropertyChanged 并尝试将所有属性设置为 null ,这可以正常工作,但是 ZXingBarcodeImageView 没有清除条形码图像,如果我尝试从集合中删除项目,仍然会抛出异常.我现在已经没有更多的想法了。

我希望有人可以帮助我。

更新 因为i 似乎令人困惑,这是我正在使用的循环

for (int i = 0; i < _barcodeCollection.Count; i++)
{
    var response =
        await _serverUrl.PostUrlEncodedAsync(
            new { barcode = _barcodeCollection[i].Text })
            .ReceiveString();

    if (string.Equals(response, "ok", StringComparison.OrdinalIgnoreCase))
    {
        percentage += progressSteps;

        _barcodeCollection.RemoveAt(i); //EXCEPTION!!!

        i--; // index must be checked twice else one element will be skipped

        await UploadProgress.ProgressTo(percentage, 250, Easing.Linear);
    }
}

【问题讨论】:

  • 你的i 是什么?当您删除了所有元素并且您仍试图从集合中删除某些内容时,不是这种情况吗?
  • i 是 for 循环的一部分 for(int i = 0; i &lt; _barcodeCollection.Count; i++) 里面是我检查的内容,如果为真,我会尝试删除元素
  • 不要在RemoveAt(i)之后增加i。
  • @Clemens 我不知道。我检查过,索引始终是我需要的索引,并且在集合中仍然可用。索引i 处的对象也永远不会为空
  • 你不在 for 循环的i++ 部分?您可能应该将该循环的代码添加到您的问题中,以便我们了解您实际在做什么。

标签: c# xaml xamarin xamarin.forms zxing


【解决方案1】:

不是一个简单的解决方案,但我发现的最简单的解决方法是在绑定 BarcodeValue 时提供 FallbackValue

<forms:ZXingBarcodeImageView BarcodeFormat="{Binding Format}" 
                             BarcodeValue="{Binding Content, FallbackValue='1'}" />

【讨论】:

    【解决方案2】:

    我已设法确定问题的原因,这是在删除元素并且 ListViewCachingStrategy 设置为 RetainElement(默认值)时刷新 ListView 的方式的副作用。 当从集合中移除项目时调用自定义渲染器 OnElementPropertyChanged,并且 ZXing 自定义渲染器中的 regenerate() 方法崩溃。 这可以通过将 ListViewCachingStrategy 设置为 RecycleElement 来解决,这将适用于 Android,但是 iOS 10 仍然存在问题,它不正确支持 ListViewCachingStrategy 设置为 RecycleElement 的列表视图,iOS 10 目前仅适用于 ListViewCachingStrategy 设置为 RetainElement ,如果您在可移植代码中创建自定义控件,则可以适应这种情况,例如:

    public class MyZXingBarcodeImageView : ZXingBarcodeImageView
        {
        //THERE IS NO CODE REQUIRED HERE
        }
    

    然后根据 ZXing 源码创建自己的自定义渲染器,但将 void regenerate() 方法替换为以下内容:

    void regenerate()
        {
            if(formsView != null && !string.IsNullOrWhiteSpace(formsView.BarcodeValue) )
            {
                var writer = new ZXing.Mobile.BarcodeWriter();
    
                if(formsView != null && formsView.BarcodeOptions != null)
                    writer.Options = formsView.BarcodeOptions;
                if(formsView != null && formsView.BarcodeFormat != null)
                    writer.Format = formsView.BarcodeFormat;
    
                var value = formsView != null ? formsView.BarcodeValue : string.Empty;
    
                Device.BeginInvokeOnMainThread(() =>
                {
    
                    var image = writer.Write(value);
    
                    imageView.Image = image;
    
                    });
    
            }
        }
    

    变化发生在第一个 If 语句中,从测试空字符串更改为 string.IsNullOrWhiteSpace

    如果您使用设置为 RecycleElement 的 ListViewCachingStrategy,则不必为 Android 创建自定义渲染器,ZXingBarcodeImageView 的基本渲染器将正常使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      相关资源
      最近更新 更多