模板 10 Zxing.Mobile.Net

Template 10 Zxing.Mobile.Net

我在使用 Template 10 汉堡包模板和 Zxing.mobile.net 库时遇到问题 "Template10": "1.1.12", "ZXing.Net.Mobile": "2.1.46"

如果我将以下代码添加到 Mainpage 和 Viewmodel,扫描器将正常工作并将值绑定回 TextBox,但如果我将相同的代码添加到详细信息页面,返回的代码将不会 bind.I'我做错了什么。

Mainpage.xaml

   <Page x:Class="WindowsApp3.Views.MainPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:Behaviors="using:Template10.Behaviors"
          xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
          xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
          xmlns:controls="using:Template10.Controls"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:local="using:WindowsApp3.Views"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:vm="using:WindowsApp3.ViewModels"
          mc:Ignorable="d">

        <Page.DataContext>
            <vm:MainPageViewModel x:Name="ViewModel" />
        </Page.DataContext>

        <RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="AdaptiveVisualStateGroup">
                    <VisualState x:Name="VisualStateNarrow">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <!--  TODO: change properties for narrow view  -->
                            <Setter Target="stateTextBox.Text" Value="Narrow Visual State" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateNormal">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <!--  TODO: change properties for normal view  -->
                            <Setter Target="stateTextBox.Text" Value="Normal Visual State" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateWide">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <!--  TODO: change properties for wide view  -->
                            <Setter Target="stateTextBox.Text" Value="Wide Visual State" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <controls:PageHeader x:Name="pageHeader"
                                 RelativePanel.AlignLeftWithPanel="True"
                                 RelativePanel.AlignRightWithPanel="True"
                                 RelativePanel.AlignTopWithPanel="True"
                                 Text="Main Page">

                <!--  secondary commands  -->
                <controls:PageHeader.SecondaryCommands>
                    <AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
                    <AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
                    <AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
                </controls:PageHeader.SecondaryCommands>

            </controls:PageHeader>

            <RelativePanel EntranceNavigationTransitionInfo.IsTargetElement="True"
                           RelativePanel.AlignBottomWithPanel="True"
                           RelativePanel.AlignLeftWithPanel="True"
                           RelativePanel.AlignRightWithPanel="True"
                           RelativePanel.Below="pageHeader">


                <controls:Resizer x:Name="parameterResizer" Margin="16,16,16,0">

                    <TextBox MinWidth="150"
                             MinHeight="62"
                             Header="Parameter to pass"
                             Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                             TextWrapping="Wrap">
                        <Interactivity:Interaction.Behaviors>

                            <!--  enable submit on enter key  -->
                            <Behaviors:KeyBehavior Key="Enter">
                                <Core:CallMethodAction MethodName="GotoDetailsPage" TargetObject="{Binding}" />
                            </Behaviors:KeyBehavior>

                            <!--  focus on textbox when page loads  -->
                            <Core:EventTriggerBehavior>
                                <Behaviors:FocusAction />
                            </Core:EventTriggerBehavior>

                        </Interactivity:Interaction.Behaviors>
                    </TextBox>

                </controls:Resizer>

                <Button x:Name="submitButton"
                        Click="{x:Bind ViewModel.GotoDetailsPage}"
                        Content="Submit"
                        RelativePanel.AlignBottomWith="parameterResizer"
                        RelativePanel.RightOf="parameterResizer" />

                <TextBlock x:Name="stateTextBox"
                           Margin="16,16,0,0"
                           RelativePanel.AlignLeftWith="parameterResizer"
                           RelativePanel.Below="parameterResizer"
                           Text="Current Visual State" />



            <!--  content  -->
            <!--  content  -->
            <Button x:Name="loadButton"
                          HorizontalAlignment="Center"
                          Width="180"
                          Height="50"
                                RelativePanel.Below="stateTextBox"

                          Click="{x:Bind ViewModel.QRCodeCick}">
              <StackPanel Orientation="Horizontal">
                <SymbolIcon Width="48"
                                               VerticalAlignment="Center"
                                               Height="48"
                                                Symbol="Camera" />
                <TextBlock Margin="12,0,0,0"
                                               VerticalAlignment="Center"
                                               Text="Read QR Code" />
              </StackPanel>
            </Button>
            <TextBox x:Name="QRTextBox"
                     PlaceholderText="Enter Code"
                     Text="{x:Bind ViewModel.QRText,Mode=TwoWay}"
                    RelativePanel.Below="loadButton"
                     Margin="0,0,0,12"/>

        </RelativePanel>

        </RelativePanel>
    </Page>

MainPage.xaml.cs

using System;
using WindowsApp3.ViewModels;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using System.Collections.ObjectModel;

namespace WindowsApp3.Views
{
  public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      InitializeComponent();
      NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
    }
  }
}

MagePageViewModel.cs

using Template10.Mvvm;
using System.Collections.Generic;
using System;
using System.Linq;
using System.Threading.Tasks;
using Template10.Services.NavigationService;
using Windows.UI.Xaml.Navigation;
using ZXing.Mobile;

namespace WindowsApp3.ViewModels
{
  public class MainPageViewModel : ViewModelBase
  {
    MobileBarcodeScanner scanner;

    public MainPageViewModel()
    {
      if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
      {
        Value = "Designtime value";
      }

      //Create a new instance of our scanner
      scanner = new MobileBarcodeScanner();

      // this.Dispatcher
      //    scanner.Dispatcher = this.Dispatcher;

    }

    string _Value = "Gas";
    public string Value { get { return _Value; } set { Set(ref _Value, value); } }

    public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
    {
      if (suspensionState.Any())
      {
        Value = suspensionState[nameof(Value)]?.ToString();
      }
      await Task.CompletedTask;
    }

    public override async Task OnNavigatedFromAsync(IDictionary<string, object> suspensionState, bool suspending)
    {
      if (suspending)
      {
        suspensionState[nameof(Value)] = Value;
      }
      await Task.CompletedTask;
    }

    public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
    {
      args.Cancel = false;
      await Task.CompletedTask;
    }

    public void GotoDetailsPage() =>
        NavigationService.Navigate(typeof(Views.DetailPage), Value);

    public void GotoSettings() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 0);

    public void GotoPrivacy() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 1);

    public void GotoAbout() =>
        NavigationService.Navigate(typeof(Views.SettingsPage), 2);


    public async void QRCodeCick()
    {
      scanner.UseCustomOverlay = false;

      scanner.TopText = "Hold camera up to barcode";
      scanner.BottomText = "Camera will automatically scan barcode\r\n\r\nPress the 'Back' button to Cancel";

      //Start scanning
      var result = await scanner.Scan();

      if (result != null)
        _QRText = result.Text;
    }

    string _QRText;
    public string QRText { get { return _QRText; } set { Set(ref _QRText, value); } }

  }
}

Details.xaml

<Page x:Class="WindowsApp3.Views.DetailPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:Behaviors="using:Template10.Behaviors"
      xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
      xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
      xmlns:controls="using:Template10.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:WindowsApp3.Views"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:vm="using:WindowsApp3.ViewModels"
      x:Name="ThisPage"
      mc:Ignorable="d">

    <Page.DataContext>
        <vm:DetailPageViewModel x:Name="ViewModel" />
    </Page.DataContext>

    <RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="AdaptiveVisualStateGroup">
                <VisualState x:Name="VisualStateNarrow">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <!--  TODO: change properties for narrow view  -->
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="VisualStateNormal">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <!--  TODO: change properties for normal view  -->
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="VisualStateWide">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <!--  TODO: change properties for wide view  -->
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <!--  header  -->
        <controls:PageHeader x:Name="pageHeader"
                             Frame="{x:Bind Frame}"
                             RelativePanel.AlignLeftWithPanel="True"
                             RelativePanel.AlignRightWithPanel="True"
                             RelativePanel.AlignTopWithPanel="True"
                             Text="Detail Page" />

        <!--  content  -->
        <ScrollViewer EntranceNavigationTransitionInfo.IsTargetElement="True"
                      Padding="12,8,0,0"
                      RelativePanel.AlignBottomWithPanel="True"
                      RelativePanel.AlignLeftWithPanel="True"
                      RelativePanel.AlignRightWithPanel="True"
                      RelativePanel.Below="pageHeader"
                      VerticalScrollBarVisibility="Auto">
            <StackPanel>
                <TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="You passed:" />
                <TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Value, Mode=OneWay, FallbackValue=DesigntimeValue}" />
        <Button x:Name="loadButton"
                      HorizontalAlignment="Center"
                      Width="180"
                      Height="50"

                      Click="{x:Bind ViewModel.QRCodeCick}">
          <StackPanel Orientation="Horizontal">
            <SymbolIcon Width="48"
                                           VerticalAlignment="Center"
                                           Height="48"
                                            Symbol="Camera" />
            <TextBlock Margin="12,0,0,0"
                                           VerticalAlignment="Center"
                                           Text="Read QR Code" />
          </StackPanel>
        </Button>
        <TextBox x:Name="QRTextBox"
                 PlaceholderText="Enter Code"
                 Text="{x:Bind ViewModel.QRText,Mode=TwoWay}"
                 Margin="0,0,0,12"/>
      </StackPanel>
        </ScrollViewer>

    </RelativePanel>
</Page>

DesignPage.xaml.cs

using WindowsApp3.ViewModels;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Controls;

namespace WindowsApp3.Views
{
  public sealed partial class DetailPage : Page
  {
    public DetailPage()
    {
      InitializeComponent();
      NavigationCacheMode = NavigationCacheMode.Disabled;
    }
  }
}

DesignViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Template10.Common;
using Template10.Mvvm;
using Template10.Services.NavigationService;
using Windows.UI.Xaml.Navigation;
using ZXing.Mobile;

    namespace WindowsApp3.ViewModels
    {
      public class DetailPageViewModel : ViewModelBase
      {
        MobileBarcodeScanner scanner;

        public DetailPageViewModel()
        {
          if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
          {
            Value = "Designtime value";
          }

          //Create a new instance of our scanner
          scanner = new MobileBarcodeScanner();

          // this.Dispatcher
          //    scanner.Dispatcher = this.Dispatcher;

        }

        private string _Value = "Default";
        public string Value { get { return _Value; } set { Set(ref _Value, value); } }

        public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
        {
          Value = (suspensionState.ContainsKey(nameof(Value))) ? suspensionState[nameof(Value)]?.ToString() : parameter?.ToString();
          await Task.CompletedTask;
        }

        public override async Task OnNavigatedFromAsync(IDictionary<string, object> suspensionState, bool suspending)
        {
          if (suspending)
          {
            suspensionState[nameof(Value)] = Value;
          }
          await Task.CompletedTask;
        }

        public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
        {
          args.Cancel = false;
          await Task.CompletedTask;
        }

        public async void QRCodeCick()
        {
          scanner.UseCustomOverlay = false;

          scanner.TopText = "Hold camera up to barcode";
          scanner.BottomText = "Camera will automatically scan barcode\r\n\r\nPress the 'Back' button to Cancel";

          //Start scanning
          var result = await scanner.Scan();

          if (result != null)
            _QRText = result.Text;
        }

        string _QRText;
        public string QRText { get { return _QRText; } set { Set(ref _QRText, value); } }
      }
    }

我发现您的代码有两个问题:

1.) _QRText = result.Text 不会触发绑定的 PropertyChange。

2.) 主要区别在于页面 NavigationCacheMode 属性。您在 MainPage 上使用 NavigationCacheMode.Enabled,在 DesignPage 上使用 NavigationCacheMode.Disabled

在后台,ZXing 进行页面导航,然后进行返回导航,因此当它导航回 MainPage 时,它使用缓存版本,因此 ViewModel 也被缓存。

但在 DesignPage 中禁用了缓存,因此后退导航会创建一个新的页面和视图模型实例,因此会在 old 视图模型中调用以下代码而不是新的。

//Start scanning
var result = await scanner.Scan();

if (result != null)
    _QRText = result.Text;

因此您需要将页面的NavigationCacheMode 属性设置为NavigationCacheMode.Required开始扫描二维码的位置。