2

I've started using Template10 and are trying to put a ZXing Barcode scanner in the application. But I'm having some issues with the way ZXing and Template10 works togehter.

When I initiate the ZXing scanner it seems to write over all current frames and content with its own layout. So when I initiate the cancel action, there is nothing left to go back to.

The frame is always at the page that initiated it, so Template10 does not understand that anything is happening.

My code:

public async Task ScanQR()
{
    try
    {
        var scanner = new ZXing.Mobile.MobileBarcodeScanner();

        var _overlay = new Views.Scanner();
        _overlay._cancel.Click += (object sender, RoutedEventArgs e) => { scanner.Cancel(); };
        _overlay._torch.Click += (object sender, RoutedEventArgs e) => { scanner.ToggleTorch(); };

        scanner.CustomOverlay = _overlay;
        scanner.UseCustomOverlay = true;

        var result = await scanner.Scan();
        if (result != null)
        {
             // Handle Result
        }
    }
}

As you can see on the snapshots (1)(2) the stacked panels on the application are overwritten. As you can see it replaces the ones from [Frame]->[ContentPresenter] and inwards.

How can I make the code go back to the previous page when canceled? I understand that I probably need to capsulate this somehow, but I can't find anything about it. Been searching around to find anyone with a similar issue. So I turn to you guys.

(1). Before ZXing.Scan()

(2). After ZXing.Scan()

--- Addition Information ---

The solution to this problem on a normal application not using Template10 was to handle the back requests with the following code. This was something I found on a forum somewhere, can't remember the source now.

If this code was not present the application would just close when you press the hardware back button on a phone. When I try the Template10 project on a phone it does the same thing. On a PC you don't get a back button.

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        var currentView = SystemNavigationManager.GetForCurrentView();
        if (!ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
        {
            currentView.AppViewBackButtonVisibility = this.Frame.CanGoBack ?
                AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed;
        }
        currentView.BackRequested += SystemNavigationManager_BackRequested;
    }

    private void SystemNavigationManager_BackRequested(object sender, BackRequestedEventArgs e)
    {
        if (this.Frame.CanGoBack)
        {
            this.Frame.GoBack();
            e.Handled = true;
        }
    }
Startail
  • 67
  • 7

2 Answers2

1

Have you checked the Navigation stack to see if the previous view is there? If it is, you can easily call in to the Template10 Navigation service and call GoBack

Justin Patten
  • 1,059
  • 6
  • 16
  • That was my first thought. I tried to call NaviagtaionService.GoBack() it seems that ZXing does not make a new page/frame/view. NavigationService.CanGoBack is false and the NavigationService.Content is still "MainPage". – Startail Jul 20 '16 at 16:14
1

When I initiate the ZXing scanner it seems to write over all current frames and content with its own layout. So when I initiate the cancel action, there is nothing left to go back to.

From your pictures I think you are using Template 10 Hamburger to build your app. Then the Xaml tree is like this: Window.Current.Content -> Shell -> SplitView -> Frame -> MainPage.

Just read the source code of Zxing MobileBarcodeScanner, when create a new instance of Scanner, it will navigate from the rootFrame of the app to the Scanner/ CustomerScanner page, this is why your "Shell" is gone after Zxing.Scan(). So basically, if you need to cancel the operation/ navigate back to the last page, you can use the rootFrame.GoBack(); to go back.

Only the problem is, the rootFrame.CanGoBack is false. If you look at the code in the App.xaml.cs, in the task OnInitializeAsync, it set the "Shell" page as content of the Window.Current.Content, it doesn't use the Frame.Navigate method to navigate to the page, to make the rootFrame.CanGoBack to be true, we can manually add Shell page to Backstack like this:

if (Window.Current.Content as ModalDialog == null)
{
    // create a new frame
    var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include);
    // create modal root
    Window.Current.Content = new ModalDialog
    {
        DisableBackButtonWhenModal = true,
        Content = new Views.Shell(nav),
        ModalContent = new Views.Busy(),
    };
    var rootFrame = Window.Current.Content as Frame;
    rootFrame.BackStack.Add(new Windows.UI.Xaml.Navigation.PageStackEntry(typeof(Views.Shell), null, null));
}

Then in the Cancel method of your Scanner page:

var rootFrame = RootFrame ?? Window.Current.Content as Frame ?? ((FrameworkElement)Window.Current.Content).GetFirstChildOfType<Frame>();
if (rootFrame.CanGoBack)
{
    rootFrame.GoBack();
}
Grace Feng
  • 16,564
  • 2
  • 22
  • 45
  • Thank you for your very elaborate answer and kind help for a newcomer like me. I see what you have done here, but I have an issue on the code for the cancel method. It complains about "RootFrame" not existing in the current frame and FrameworkElement not containing GetFirstChildOfType – Startail Jul 21 '16 at 16:11
  • @Magnus, it's not a big problem, the `RootFrame` just need to be define outside of this method like `public Frame RootFrame;`, and `GetFirstChildOfType` method belongs to ZXing.Mobile, you need to use this namespace in the code. – Grace Feng Jul 22 '16 at 01:20