Is there a way to render the Zxing ScannerPage in Xaml?

I'm using the MVVM approach to make a small scanner app. I have a startPage.Xaml with one button binded to a command in the viewModel that opens my scannerPage.Xaml On the scannerPage I have just a simple footer, and want the scanner object to fill the rest of the page. However, when I add the scanner object to my stackPanel I get the following exception: "System.MissingMethodException: Default constructor not found for type ZXing.Net.Mobile.Forms.ZXingScannerPage". I'll list my xaml code below. Any help will be much appreciated. Thanks

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:forms="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
             xmlns:custom="using:MobiNative_Forms.Views"
             x:Class="MobiNative_Forms.Views.BarcodePage"
             BackgroundColor="Transparent">
  <ContentPage.Content>
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="8.5*" />
        <RowDefinition Height="1.5*" />
      </Grid.RowDefinitions>
      <StackLayout x:Name="layout2" Grid.Row="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
        <forms:ZXingScannerPage></forms:ZXingScannerPage>
      </StackLayout>
      <Label Grid.Row="1" Text="MOBI" FontSize="Large" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" BackgroundColor="Blue"/>
    </Grid>
  </ContentPage.Content>
</ContentPage>

Answers

  • KellyHussKellyHuss USMember ✭✭

    The ZXingScannerPage is a page, not a view. Maybe try ZXingScannerView instead?

  • DougMaurerDougMaurer USMember ✭✭

    @KrzysztofKazmierczak , I am using your suggestions but am confused on where to put the events for the actual scanning. I am using an mvvm model (prism) so I have a viewmodel set for this page. What would the events look like in that model to be able to receive the scan, etc.?

  • DougMaurerDougMaurer USMember ✭✭

    Awesome! I got my app working!

    But, alas, a follow-up situation. After 1 scan, the scanner window is stuck on the last image. How do I get the scanner to scan an item, update an entry on screen (for example), and then get right back to scanning?

  • LinnKristinLinnKristin NOUniversity ✭✭

    What version of ZXing are U using ?
    Some how I can get the full screen to work but not in the view- I don´t get a camera preview. It does not react to hitting flash either. Thinking maybe it is a version problem ?
    IsScanning is set to true

  • SimonFagerliSimonFagerli USMember

    @LinnKristin
    I seem to be experiencing the same issues - I get the pageView to function as I want, but the view doesn't function as I want.
    I'm using version 2.3.2 with .NET Standard 2.0.

    I'm switching view between the content with a button for showing the QR scanner and first time it "works" to an extend in the sense that I can see the QR scanner and it calls the ScanResultCommand, but does not fill in the Result even though Ive binded it to a variable in the viewmodel with mode set as twoway.
    The result does not get set at all and remains empty. Next time I "activate" the view, the camera view is simply black.
    Torch button doesnt function either.

  • hrithickhrithick Member ✭✭
    @KrzysztofKazmierczak how to bind scanner result to entry after scannin
  • KrzysztofKazmierczakKrzysztofKazmierczak USMember ✭✭

    @udaysaikumar - I cannot test it now, but did you try to bind your entry to viewmodel's Result property?

    private ZXing.Result result;
    public ZXing.Result Result
    {
    get { return this.result; }
    set
    {
    if (!string.Equals(this.result, value))
    {
    this.result = value;
    this.OnPropertyChanged(nameof(Result));
    }
    }
    }

    I will check this as soon as possible.

    Best
    Krzysztof

  • KrzysztofKazmierczakKrzysztofKazmierczak USMember ✭✭

    @udaysaikumar - simply bind your entry to Result.Text. Please check my sampe xaml:

    <?xml version="1.0" encoding="utf-8" ?>

    <ContentPage.Content>

        <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
            <Grid.RowDefinitions>
                <RowDefinition Height="40" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <forms:ZXingScannerView Grid.Row="1" IsScanning="{Binding IsScanning}" IsAnalyzing="{Binding IsAnalyzing}" Result="{Binding Result, Mode=TwoWay}"></forms:ZXingScannerView>
            <forms:ZXingDefaultOverlay Grid.Row="1" TopText="Coma" BottomText="Dr" ShowFlashButton="False" Opacity="0.9"></forms:ZXingDefaultOverlay>
            <Entry Grid.Row="0" Text="{Binding Result.Text}"></Entry>
        </Grid>
    
    </ContentPage.Content>
    

    And sample viewmodel:

    using System.ComponentModel;

    namespace Forum
    {
    public class QRCodeScannerViewModel : INotifyPropertyChanged
    {
    private ZXing.Result result;
    public ZXing.Result Result
    {
    get { return this.result; }
    set
    {
    if (!string.Equals(this.result, value))
    {
    this.result = value;
    this.OnPropertyChanged(nameof(Result));
    }
    }
    }

        private bool isAnalyzing = true;
        public bool IsAnalyzing
        {
            get { return this.isAnalyzing; }
            set
            {
                if (!bool.Equals(this.isAnalyzing, value))
                {
                    this.isAnalyzing = value;
                    this.OnPropertyChanged(nameof(IsAnalyzing));
                }
            }
        }
    
        private bool isScanning = true;
        public bool IsScanning
        {
            get { return this.isScanning; }
            set
            {
                if (!bool.Equals(this.isScanning, value))
                {
                    this.isScanning = value;
                    this.OnPropertyChanged(nameof(IsScanning));
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler changed = PropertyChanged;
            if (changed != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    }

    Please let me know if I can be of any more help on this!

    best regards!
    Krzysztof

  • hrithickhrithick Member ✭✭
    edited May 2018

    @KrzysztofKazmierczak this is working fine... how to do this in code behind??? i am binding value from anotherpage to same entry using messaging center getting object reference not set to an instance..

  • chrisrinerchrisriner Member ✭✭

    Anyone know how to set the options in XAML. I tried in XAML and I tried binding the options and no matter what I can't seem to get the options to take such as having it use the front facing camera but I can in code.

  • Rameshbodh_Rameshbodh_ Member ✭✭
    edited April 9

    @DougMoore

    Awesome! I got my app working!

    But, alas, a follow-up situation. After 1 scan, the scanner window is stuck on the last image. How do I get the scanner to scan an item, update an entry on screen (for example), and then get right back to scanning?

    I think this could help

    clearing Grid before adding zxingscanner view

    zxing = new ZXingScannerView
    {
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.FillAndExpand,
    AutomationId = "ZxingScannerView"
    };

            zxing.IsScanning = true;
            zxing.OnScanResult += Zxing_OnScanResult;
            grdScannerView.Children.Clear();
            grdScannerView.Children.Add(zxing);> @DougMaurer said:
    
  • DevMaranDevMaran Member ✭✭
    edited May 26

    @KrzysztofKazmierczak said:
    @udaysaikumar - I cannot test it now, but did you try to bind your entry to viewmodel's Result property?

    private ZXing.Result result;
    public ZXing.Result Result
    {
    get { return this.result; }
    set
    {
    if (!string.Equals(this.result, value))
    {
    this.result = value;
    this.OnPropertyChanged(nameof(Result));
    }
    }
    }

    I will check this as soon as possible.

    Best
    Krzysztof

    hi @KrzysztofKazmierczak I have used your solution but "QRScanResultCommand" execute only once

    public class BarCodeViewModel : INotifyPropertyChanged
        {
            public bool isScanning = true;
            //public bool IsVisible { get; set; }
            public ICommand ScanNext { get; private set; }
    
            public BarCodeViewModel()
            {
                ScanNext = new Command(() => scanNext());
            }
    
            private ZXing.Result result;
            public ZXing.Result Result
            {
                get { return this.result; }
                set
                {
                    if (!string.Equals(this.result, value))
                    {
                        this.result = value;
                        this.OnPropertyChanged(nameof(Result));
                    }
                }
            }
    
    
            public bool _isScanning = true;
            public bool IsScanning
            {
                get { return this._isScanning; }
                set
                {
                    if (!bool.Equals(this._isScanning, value))
                    {
                        this._isScanning = value;
                        this.OnPropertyChanged(nameof(IsScanning));
                    }
                }
            }
    
            public bool _isAnalyzing = true;
            public bool IsAnalyzing
            {
                get { return this._isAnalyzing; }
                set
                {
                    if (!bool.Equals(this._isAnalyzing, value))
                    {
                        this._isAnalyzing = value;
                        this.OnPropertyChanged(nameof(IsAnalyzing));
                    }
                }
            }
    
    
            public Command QRScanResultCommand
            {
                get
                {
                    return new Command(() =>
                    {
                        IsAnalyzing = false;
                        IsScanning = false;
    
                        Device.BeginInvokeOnMainThread(async () =>
                        {
                            //await DisplayAlert("Scanned result", result.Text, "OK");
                            //Console.WriteLine("scan result :==============================:" + Result.Text);
                        });
                    });
                }
            }
    
            // this method executes when clicking on the button
            public void scanNext()
            {
                IsAnalyzing = true;
                IsScanning = true;
            }
    
    
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs((propertyName)));
            }
    

    XAML:

    <StackLayout Margin="0" Padding="0">
            <StackLayout BackgroundColor="#46545D" Orientation="Horizontal" HeightRequest="50" Margin="0" Padding="0">
                <StackLayout Orientation="Horizontal" VerticalOptions="Center">
                    <Button TextColor="White" Text="&lt;" HorizontalOptions="Start" FontSize="30" BackgroundColor="#46545D" WidthRequest="50" Padding="0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="EndAndExpand">
                    <Button TextColor="White" Text="Next" Font="Bold,15" HorizontalOptions="EndAndExpand" BackgroundColor="#46545D" WidthRequest="50" Padding="0" Command="{Binding ScanNext}" />
                    <Button TextColor="White" Text="Finish" Font="Bold,15" HorizontalOptions="EndAndExpand" BackgroundColor="#46545D" WidthRequest="70" Padding="0" />
                </StackLayout>
            </StackLayout>
            <StackLayout x:Name="scanerView" HeightRequest="250" VerticalOptions="StartAndExpand" BackgroundColor="#31383E" Margin="0" Padding="0">
                <Grid x:Name="mainGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <zxing:ZXingScannerView HeightRequest="250" IsScanning="{Binding IsScanning}" IsAnalyzing="{Binding IsAnalyzing}" Result="{Binding Result, Mode=TwoWay}" ScanResultCommand="{Binding QRScanResultCommand}"/>
                    <!--<zxing:ZXingScannerView x:Name="_scanView" WidthRequest="250" HeightRequest="250" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" OnScanResult="Handle_OnScanResult"/>-->
                    <zxing:ZXingDefaultOverlay x:Name="scanOverlay" TopText="Hold your phone up to the barcode" BottomText="Scanning will happen automatically" ShowFlashButton="false" Opacity="0.9" />
                </Grid>
            </StackLayout>
    
  • ilovefoxilovefox Member
    Sorry I don’t have good english.
    Remove this code
    IsScanning = false;
Sign In or Register to comment.