Ticket T867142
Visible to All Users

XAF Blazor - How to implement a QR / barcode scanner using a camera of a mobile device

created 5 years ago

Hello, will the 20.1 release support any method to allow external plugins like in this https://community.devexpress.com/blogs/xaf/archive/2017/06/29/how-to-use-a-barcode-scanner-in-xaf-mobile.aspx ?
Thank you, Paolo

Show previous comments (9)

    Hi all, I've created an application that read a barcode and open the related product, as you can see in the attached video. With a specific javascript library and the DxGalley component is relative simple to implement a barcode scanner in a XAF Blazor app ;)

    DevExpress Support Team 3 years ago

      Hi Emanuele,

      Thank you for your reply. We will appreciate it if you can share your solution or more detailed steps/tricks to implement this usage scenario. This will help other users who may encounter this issue.

      Thanks,
      Stanley

      PL PL
      Paolo Liverani 3 years ago

        Hello Emanuele,
        that is really nice!!!
        Could you explain how you managed that?
        Thank you, Paolo
        PS: sei italiano?

        Answers approved by DevExpress Support

        created 3 years ago (modified 3 years ago)

        Hi all,

        the solution is simply based on this ticket https://supportcenter.devexpress.com/ticket/details/t943982 and others.
        Basically, I've created a custom View Item for the "cam open" button, then I added the custom View Item to a Dashboard View.

        BarcodeCamDVI

        C#
        using DevExpress.ExpressApp; using DevExpress.ExpressApp.Blazor; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using Microsoft.AspNetCore.Components; using System; namespace MyProject.Module.Blazor.Editors { public interface IModelBarcodeCamDVI : IModelViewItem { } [ViewItem(typeof(IModelBarcodeCamDVI))] public class BarcodeCamDVI : ViewItem { public class DxButtonHolder : IComponentContentHolder { private readonly View currentView; public DxButtonHolder(View _currentView) { this.currentView = _currentView; } RenderFragment IComponentContentHolder.ComponentContent => RazorComponents.BarcodeCamButton.Create(currentView); } public BarcodeCamDVI(IModelViewItem model, Type objectType) : base(objectType, model.Id) { } protected override object CreateControlCore() => new DxButtonHolder(this.View); } }

        ArticoloGetInvokeHelper

        C#
        using Microsoft.JSInterop; using System; namespace MyProject.Module.Blazor.Editors { public class ArticoloGetInvokeHelper { private Action<SearchItemArticolo> action; public ArticoloGetInvokeHelper(Action<SearchItemArticolo> action) { this.action = action; } [JSInvokable] public void SearchRecordCaller(SearchItemArticolo param) { this.action.Invoke(param); } } public class SearchItemArticolo { public string Barcode { get; set; } } }

        Next, I created a new Navigation Item for the Dashboard View, and a razor component containing the gallery and the DxButton elements:

        BarcodeCam.razor

        Razor
        ... <h3>BarcodeCamButton</h3> <DxButton Text="Apri Fotocamera" Click="Button_Click" /> <div id="gallery"></div> <div id="scanStatus"></div> ... @code { [Parameter] public View View { get; set; } private IObjectSpace objectSpace; // protected async void Button_Click(MouseEventArgs e) { var app = ApplicationProvider.GetApplication(); IList<Articolo> Articoli = objectSpace.GetObjects<Articolo>(); await JSRuntime.InvokeVoidAsync("ScannerFunctions.StartCamStreaming", DotNetObjectReference.Create(articoloGetInvokeHelper)); } private Editors.ArticoloGetInvokeHelper articoloGetInvokeHelper; // protected override void OnInitialized() { articoloGetInvokeHelper = new Editors.ArticoloGetInvokeHelper(SearchRecord); } // protected override async Task OnAfterRenderAsync(bool firstRender) { objectSpace = View.ObjectSpace; } // private async void SearchRecord(Editors.SearchItemArticolo param) { //var obj = objectSpace.GetObjectByKey<Articolo>(param.Key); var obj = objectSpace.GetObjects<Articolo>().FirstOrDefault(a => a.Barcode == param.Barcode); if (obj == null) { await JSRuntime.InvokeVoidAsync("ScannerFunctions.ShowScanStatus", $"Barcode {param.Barcode} not found"); return; } var app = ApplicationProvider.GetApplication(); IObjectSpace objSpace = app.CreateObjectSpace(typeof(Articolo)); Articolo art = objSpace.GetObject<Articolo>(obj); if (art != null) { DetailView createdView = app.CreateDetailView(objSpace, art); createdView.ViewEditMode = ViewEditMode.View; app.MainWindow.SetView(createdView); } } // void IDisposable.Dispose() { objectSpace?.Dispose(); } public static RenderFragment Create(View view) =>@<BarcodeCamButton View=@view />; ... }

        Finally, in the Javascript code I implemented the cam functions (start, close, restart etc.) using (in my case) the external library ZXing:
        https://github.com/zxing-js/browser
        The gallery content (cam streams) come from Navigator.mediaDevices:

        JavaScript
        var gallery = []; navigator.mediaDevices.enumerateDevices().then(function (devices) { ... for (var i = 0; i < devices.length; i++) { gallery.push(devices[i]); } ... $("#gallery").dxGallery({ dataSource: gallery, ... });

        If you are interested, I could try to create a sample project with this functionality and share it with you (after correcting and fixing all the code I have implemented now ;)) or enrich the synthetic explanation above.
        Ps: ciao Paolo, sì sono italiano! :D

        Best regards!

          Show previous comments (2)
          Dennis Garavsky (DevExpress) 3 years ago

            Thank you for sharing your code with other XAFers, Emanuele.

            PL PL
            Paolo Liverani 3 years ago

              Hello Emanuele,
              I have tried it: quite smart your implementation!
              You have added a great feature to XAF.
              Thank you very much, Paolo

                Thanks to Emanuele for sharing the code.
                Very usefull.

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.