0

The following code results in a System.ObjectDisposedException on the line Close(result); in BarcodeScannerPopup.xaml.cs when a barcode is detected by the CameraBarcodeReaderView.

The detected barcode is correctly displayed in the label in BarcodePage.

Any idea why this exception is thrown?

BarcodePage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage
        x:Class="MyApp.BarcodePage"
        x:DataType="vm:BarcodeViewModel"
        xmlns:vm="clr-namespace:MyApp.ViewModels"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    
        <VerticalStackLayout
            Margin="20">
    
            <Label
                Text="{Binding Barcode}"/>
            <Button
                Command="{Binding ScanBarcodeClickCommand}"
                Text="Scan barcode"/>
        </VerticalStackLayout>
    </ContentPage>

BarcodePage.xaml.cs

    using MyApp.ViewModels;

    namespace MyApp.Views;
    
    public partial class BarcodePage : ContentPage
    {
        public BarcodePage(BarcodeViewModel viewModel)
        {
            InitializeComponent();
            BindingContext = viewModel;
        }
    }

BarcodeScannerPopup.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <toolkit:Popup
        x:Class="MyApp.BarcodeScannerPopup"
        xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI"
        xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    
        <VerticalStackLayout
            Margin="20">
    
            <Label
                Text="Add a barcode by scanning it."
                VerticalOptions="Center"
                HorizontalOptions="Center"/>
    
            <zxing:CameraBarcodeReaderView
                x:Name="barcodeReader"
                BarcodesDetected="BarcodesDetected"
                HeightRequest="300"
                IsDetecting="True"
                Margin="5"
                WidthRequest="300"/>
    
        </VerticalStackLayout>
    </toolkit:Popup>

BarcodeScannerPopup.xaml.cs

    using CommunityToolkit.Maui.Views;
    using ZXing.Net.Maui;
    
    namespace MyApp.Views;
    
    public partial class BarcodeScannerPopup : Popup
    {
        public BarcodeScannerPopup()
        {
            InitializeComponent();
    
            barcodeReader.Options = new BarcodeReaderOptions
            {
                AutoRotate = true,
                Multiple = false
            };
        }
    
        private void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
        {
            var result = e.Results[0].Value;
    
            Close(result);
        }
    }

BarcodeViewModel.cs

    using CommunityToolkit.Maui.Views;
    using CommunityToolkit.Mvvm.ComponentModel;
    using CommunityToolkit.Mvvm.Input;
    using MyApp.Views;
    
    namespace MyApp.ViewModels;

    public partial class BarcodeViewModel : ObservableObject
    {
        [ObservableProperty]
        private string _barcode;
    
        private BarcodeScannerPopup _popup = new BarcodeScannerPopup();
    
        [RelayCommand]
        public async Task ScanBarcodeClick()
        {
            Barcode = (string)await Application.Current.MainPage.ShowPopupAsync(_popup);
        }
    }
Niels R.
  • 7,260
  • 5
  • 32
  • 44
  • 1
    do you have a stack trace? – Jason Sep 27 '22 at 21:01
  • 1
    Niels, perhaps scanner tries to continue sending data after popup closes. I'm not familiar with this, but I would try these two lines before `Close(result);`: `barcodeReader.IsDetecting = false;` and `var result = (e.Results != null && e.Results.Length > 0 ? e.Results[0].Value : "");` – ToolmakerSteve Sep 28 '22 at 01:18
  • @Jason: The stack traces was of no use. It only contained [External Code] and the line where the exception occurred. – Niels R. Sep 28 '22 at 05:03
  • 1
    @ToolmakerSteve: You're right. The scanner continues sending data. I've updated the code and added it as an answer for future reference. Thanks! – Niels R. Sep 28 '22 at 05:04

1 Answers1

1

@ToolmakerSteve was right. The CameraBarcodeReaderView continues sending data which results in the System.ObjectDisposedException. setting the IsDetecting property to false prevents this. As this was a PoC I didn't add a proper null check on e, so I've added as a good coding practise in this example.

BarcodeScannerPopup.xaml.cs

    using CommunityToolkit.Maui.Views;
    using ZXing.Net.Maui;
    
    namespace MyApp.Views;
    
    public partial class BarcodeScannerPopup : Popup
    {
        public BarcodeScannerPopup()
        {
            InitializeComponent();
    
            barcodeReader.Options = new BarcodeReaderOptions
            {
                AutoRotate = true,
                Multiple = false
            };
        }
    
        private void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
        {
            var result = e?.Results?.Any() == true
                ? e.Results[0].Value
                : string.Empty;
    
            IsDetecting = false;

            Close(result);
        }
    }
Niels R.
  • 7,260
  • 5
  • 32
  • 44