How do I Scan with ZXingScannerView using MVVM pattern? (updated with Code)

L0gicaL1nsanityL0gicaL1nsanity Member ✭✭
edited May 17 in Xamarin.Forms

Hey all,

I'm new to the Xamarin community and hope to continue to be involved in this space, so hopefully you'll see a lot of me in the coming weeks/months! I'm curious if anyone here has happened to use the Zxing.Net.Mobile library for barcode scanning in their Xamarin Forms app and can point to an example of that? I was able to get it working using their page control, but in the MVVM pattern, I'm having trouble wiring up the scanning correctly, I guess, because nothing happens when putting a barcode in front of the red line.

Any advice is greatly appreciated!

Posts

  • L0gicaL1nsanityL0gicaL1nsanity Member ✭✭
    edited May 17

    As an added detail, I am able to get the scan event to fire, but now the visuals all disappeared. I'm trying now to add a default overlay around the scanner view to add the visuals again, but they look a little crazy.

    The look i'm going for is to have the entire screen show the camera view with the overlay visuals "overlayed" over the top.

    Classes below:

    ScanningView.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="RMAGo.Features.Scanning.ScanningView"             
                 xmlns:viewModelBase="clr-namespace:RMAGo.Framework;assembly=RMAGo" 
                 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
                 xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
                 Title="Scanning">   
    
    
                <zxing:ZXingDefaultOverlay                                
                    x:Name="scannerOverlay"                                                       
                    BottomText="Place the red line over the barcode you'd like to scan.">
    
                    <zxing:ZXingScannerView      
                        VerticalOptions="FillAndExpand"
                        HorizontalOptions="FillAndExpand"               
                        IsScanning="{Binding IsScanning}" 
                        IsAnalyzing="{Binding IsAnalyzing}"
                        Result="{Binding Result, Mode=TwoWay}" 
                        ScanResultCommand="{Binding ScanCommand}" />                       
    
                </zxing:ZXingDefaultOverlay> 
    </ContentPage>
    

    ScanningViewModel.cs

    using RMAGo.Features.Common;
    using RMAGo.Features.Navigation;
    using RMAGo.Features.Settings;
    using RMAGo.Framework;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Forms;
    using ZXing;
    using ZXing.Mobile;
    using ZXing.Net.Mobile.Forms;
    
    namespace RMAGo.Features.Scanning
    {
        public class ScanningViewModel : ViewModelBase
        {
            private readonly IRMAApiService _rmaApiService;
            private readonly ISettingsService _settingsService;
            private readonly IDialogService _dialogService;
            private readonly INavigationService _navigationService;
    
            private string barcode = string.Empty;
            public string Barcode
            {
                get
                {
                    return barcode;
                }
                set
                {
                    barcode = value;
                }
            }       
    
            private bool _isAnalyzing = true;
            public bool IsAnalyzing
            {
                get { return _isAnalyzing; }
                set
                {
                    if (!Equals(_isAnalyzing, value))
                    {
                        _isAnalyzing = value;
                    }
                }
            }        
    
            private bool _isScanning = true;
            public bool IsScanning
            {
                get { return _isScanning; }
                set
                {
                    if (!Equals(_isScanning, value))
                    {
                        _isScanning = value;
                    }
                }
            }       
    
            public Command ScanCommand
            {
                get
                {
                    return new Command(() =>
    
                    {
                        IsAnalyzing = false;
                        IsScanning = false;
    
                        Device.BeginInvokeOnMainThread(async () =>
                        {
                            Barcode = Result.Text;
                            await _dialogService.ShowAlertAsync("Scanned Item", Result.Text, "Ok");
                        });
    
                        IsAnalyzing = true;
                        IsScanning = true;
                    });               
                }
            }
            public Result Result { get; set; }        
            public ScanningViewModel(IRMAApiService rmaApiService, ISettingsService settingsService, IDialogService dialogService, INavigationService navigationService)
            {
                _rmaApiService = rmaApiService;
                _settingsService = settingsService;
                _dialogService = dialogService;
                _navigationService = navigationService;
    
    
                PropertyChanged += ScanningViewModel_PropertyChanged;
            }
    
            private void ScanningViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {           
            }
        }
    }
    
    

    Results Screenshot

  • L0gicaL1nsanityL0gicaL1nsanity Member ✭✭

    Update: I've found my solution. I saw this sample file on github that added the overlay and the scanning view to the grid directly as children: https://github.com/Redth/ZXing.Net.Mobile/blob/master/Samples/Forms/Core/CustomScanPage.cs

    Once I saw that I pretty much just followed the same approach but in xaml. (Note: I got stuck for awhile because I was listing the Overlay and THEN the scanner view. The order matters, because I guess each one is being laid out on top of the other, so overlay must come second to be the last one written on top)

    ScanningView.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="RMAGo.Features.Scanning.ScanningView"             
                 xmlns:viewModelBase="clr-namespace:RMAGo.Framework;assembly=RMAGo" 
                 viewModelBase:ViewModelLocator.AutoWireViewModel="true"
                 xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
                 Title="Scanning">   
    
    
    
        <Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <zxing:ZXingScannerView                                      
                        IsScanning="{Binding IsScanning}" 
                        IsAnalyzing="{Binding IsAnalyzing}"
                        Result="{Binding Result, Mode=TwoWay}" 
                        ScanResultCommand="{Binding ScanCommand}" />    
             <zxing:ZXingDefaultOverlay               
                    x:Name="scannerOverlay"                                                       
                    BottomText="Place the red line over the barcode you'd like to scan." />            
    
        </Grid>   
    
    </ContentPage>
    
Sign In or Register to comment.