Xamarin Forms code behind binding and accessing xaml controls

Viewed 191

I am having an issue that is hopefully rather simple. I am creating a simple xamarin forms app that uses zxing to scan a barcode and currently I just want it to display that in the entry field on the form but the binding doesn't work and neither does the commented code that just sets the value from the code behind. In fact for some reason in this simple project directly accessing the form items from the code behind just freezes the app when debugging. Hoping someone can point out some simple issue in the code causing this. 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:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms" 
         x:Class="Inventory.MainPage">
<ContentPage.Content>
    <StackLayout>
        <Grid x:Name="gridScanner">
            <zxing:ZXingScannerView x:Name="zxing" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" OnScanResult="ZXingScannerView_OnScanResult" />
            <zxing:ZXingDefaultOverlay x:Name="overlay" TopText="" BottomText="Barcode will be scanned automatically" ShowFlashButton="False" />
        </Grid>
        <StackLayout>
            <Label x:Name="lblSku" Text="SKU" FontAttributes="Bold" FontSize="Title"/>
            <Entry x:Name="txtSku" Placeholder="SKU" ReturnType="Next" />
        </StackLayout>
    </StackLayout>
</ContentPage.Content>
    public MainPage()
    {
        

        InitializeComponent();
        _currentItem = new ScanItem();
        txtSku.BindingContext = _currentItem.SKU;
        txtSku.SetBinding(Entry.TextProperty, "Value");

        zxing.IsScanning = true;
    }

    public void ZXingScannerView_OnScanResult(Result result)
    {
        _currentItem.SKU = result.Text;
        //txtSku.Text = result.Text;

    }
1 Answers

I've done the exact same thing you want without using ScannerView. I have a CollectionView, an Entry and a Button in my page. The CollectionView is irrelevant here so i will skip it. My Button opens a Scanner.

<Button Text="QR Scan"
    Grid.Column="1"
    Grid.Row="1"
    TextColor="White"
    CornerRadius="30"
    Clicked="ButtonScan" />

My Entry is:

<Entry Grid.ColumnSpan="2"
    BackgroundColor="White"
    IsTextPredictionEnabled="False"
    TextTransform="Uppercase"
    FontSize="Body"
    TextChanged="Search"
    Placeholder="Αναζήτηση"
    TextColor="Black"
    PlaceholderColor="Black"
    x:Name="lblBarcode"
    Keyboard="Chat"/>

The clicked event:

private async void ButtonScan(object sender, EventArgs e)
    {
        try
        {
            IQrScanningService scanner = DependencyService.Get<IQrScanningService>();
            string result = await scanner.ScanAsync();
            if (result == "noPermission")
            {
                await DisplayAlert("Permissions", "No permissions to access camera.", "ΟΚ");
                //Environment.Exit(1);
            }
            if (result != null && result != "")
            {
                lblBarcode.Text = result; // <--- This works for me.
                //collectionView.FilterString = "Contains([VoucherString], " + result + ")";
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

I'm using a Service to open the Scanner. It can be done with other ways too but i went with this.

public class QrScanningService : IQrScanningService
{
    public async Task<string> ScanAsync()
    {
        if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.Camera) != (int)Permission.Granted)
        {
            return "noPermission";
        }
        MobileBarcodeScanningOptions optionsCustom = new MobileBarcodeScanningOptions();

        MobileBarcodeScanner scanner = new MobileBarcodeScanner()
        {
            UseCustomOverlay = false,
            TopText = "Scan the Barcode",
            BottomText = "Align the red line with the barcode"
        };

        ZXing.Result scanResult = await scanner.Scan(optionsCustom);
        return scanResult?.Text;
    }
}

EDIT

Simpler way is to not use a service.

MobileBarcodeScanner scanner1 = new MobileBarcodeScanner();
var result1 = await scanner1.Scan();
lblBarcode.Text = result1.Text;
scanner1.Cancel();
Related