UWP/Win10新特性系列—UserConsentVerifier

时间:2022-05-05 19:32:30

在UWP开发中,微软提供了新的用户许可验证方式-指纹(生物识别)、Pin、密码验证。在爆料的新型Win10 Mobile移动设备中,会增加虹膜识别等先进的用户身份识别技术,微软现在统一了身份验证的API,将生物识别认证和传统的密码识别封装为系统API供开发者调用,调用者只需关心认证的结果,而无需担心用户使用的是虹膜识别还是指纹还是密码等其他的识别技术。

通过UserConsentVerifier类可以提高应用程序的安全性,例如,你可以授权应用程序的购买,或者访问受限制的资源之前需要指纹验证。下面看下的UserConsentVerifier类结构。

Windows.Security.Credentials.UI. UserConsentVerifier 类中,微软提供了两个静态方法:

public static IAsyncOperation<UserConsentVerifierAvailability> CheckAvailabilityAsync();

public static IAsyncOperation<UserConsentVerificationResult> RequestVerificationAsync(System.String message);

CheckAvailabilityAsync()方法是用来检测用户的身份识别器是否可用

RequestVerificationAsync() 方法是请求用户身份识别,参数为身份验证对话框的提示语

下面我们使用个例子展示下这个新的识别技术的使用。

首先我们创建一个页面,使用SplitView做一个带有汉堡包菜单的页面MainPage.xaml

 <Page.Resources>
<local:ScenarioBindingConverter x:Key="ScenarioConverter"></local:ScenarioBindingConverter>
</Page.Resources> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="wideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="641" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Splitter.DisplayMode" Value="Inline"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="narrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Splitter.DisplayMode" Value="Overlay"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView x:Name="Splitter" IsPaneOpen="True" Grid.Column="1">
<SplitView.Pane>
<RelativePanel Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
<StackPanel x:Name="HeaderPanel" Orientation="Horizontal">
<TextBlock x:Name="Header" Text="Windows 10 sample" Style="{StaticResource TagLineTextStyle}" Margin="0,15,0,0" />
</StackPanel>
<TextBlock x:Name="SampleTitle" Text="Sample Title Here" Style="{StaticResource SampleHeaderTextStyle}" TextWrapping="Wrap" RelativePanel.Below="HeaderPanel" Margin="0,10,0,0"/>
<ListBox x:Name="ScenarioControl" SelectionChanged="ScenarioControl_SelectionChanged"
SelectionMode="Single" HorizontalAlignment="Left" Style="{StaticResource ScenarioListBoxStyle}"
VerticalAlignment="Top" RelativePanel.Below="SampleTitle" Margin="0,10,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ScenarioConverter}}" Style="{StaticResource ListItemTextStyle}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</RelativePanel>
</SplitView.Pane>
<RelativePanel>
<Frame x:Name="ScenarioFrame" Margin="0,5,0,0" RelativePanel.AlignTopWithPanel="True" RelativePanel.Above="StatusPanel"/>
<StackPanel x:Name="StatusPanel" Orientation="Vertical" RelativePanel.AlignBottomWithPanel="True">
<TextBlock x:Name="StatusLabel" Margin="0,0,0,10" TextWrapping="Wrap" Text="Status:" />
<Border x:Name="StatusBorder" Margin="0,0,0,0" Visibility="Collapsed" >
<TextBlock x:Name="StatusBlock" FontWeight="Bold" MaxHeight="200" MinWidth="{Binding ElementName=Splitter, Path=ActualWidth}" TextTrimming="CharacterEllipsis" Margin="20,10,10,20" TextWrapping="Wrap"/>
</Border>
</StackPanel>
</RelativePanel>
</SplitView>
<Border Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
<ToggleButton Style="{StaticResource SymbolButton}" Click="Button_Click" VerticalAlignment="Top" Foreground="{ThemeResource ApplicationForegroundThemeBrush}">
<ToggleButton.Content>
<FontIcon x:Name="Hamburger" FontFamily="Segoe MDL2 Assets" Glyph="" Margin="0,10,0,0"/>
</ToggleButton.Content>
</ToggleButton>
</Border>
</Grid>

上面用到的样式文件如下:

 <Style x:Key="SymbolButton" TargetType="ToggleButton">
<Setter Property="Background" Value="{ThemeResource ToggleButtonBackgroundThemeBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource ToggleButtonForegroundThemeBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderThemeBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource ToggleButtonBorderThemeThickness}"/>
<Setter Property="Padding" Value="12,4,12,5"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate"/>
<VisualState x:Name="IndeterminatePointerOver">
</VisualState>
<VisualState x:Name="IndeterminatePressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminateDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualWhite"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualBlack"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
<VisualState x:Name="PointerFocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="1.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" StrokeDashArray="1,1"/>
<Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="0.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}" StrokeDashArray="1,1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <Style x:Key="BasicTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style> <Style x:Key="TagLineTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontSize" Value="16"/>
</Style> <Style x:Key="SampleHeaderTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontSize" Value="26.667"/>
</Style> <Style x:Key="ListItemTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Semilight"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style> <Style x:Key="CopyrightTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
</Style> <Style x:Key="ScenarioHeaderTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontSize" Value="26.667"/>
</Style> <Style x:Key="ScenarioDescriptionTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontSize" Value="16"/>
</Style> <Style x:Key="BaseMessageStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Semilight"/>
<Setter Property="FontSize" Value="14.667"/>
<Setter Property="Margin" Value="0,0,0,5"/>
</Style> <Style x:Key="SeparatorStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="9"/>
<Setter Property="Foreground" Value="Gray"/>
</Style> <Style x:Key="HyperlinkStyle" TargetType="HyperlinkButton">
<Setter Property="Padding" Value="1"/>
<Setter Property="Foreground" Value="Gray"/>
</Style> <!-- Default style for Windows.UI.Xaml.Controls.ListBoxItem -->
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="Padding" Value="8,10" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PressedBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="InnerGrid"
Background="Transparent">
<Rectangle x:Name="PressedBackground"
Fill="{ThemeResource ListBoxItemPressedBackgroundThemeBrush}"
Opacity="0" />
<ContentPresenter x:Name="ContentPresenter"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
<Rectangle x:Name="FocusVisualWhite"
Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset=".5" />
<Rectangle x:Name="FocusVisualBlack"
Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <Style x:Key="ScenarioListBoxStyle" TargetType="ListBox">
<Setter Property="Foreground" Value="{ThemeResource ListBoxForegroundThemeBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="{ThemeResource ListBoxBorderThemeThickness}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="True"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled"/>
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True"/>
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="Transparent"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border x:Name="LayoutRoot" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="ScrollViewer" AutomationProperties.AccessibilityView="Raw" BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Padding="{TemplateBinding Padding}" TabNavigation="{TemplateBinding TabNavigation}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

然后在App.xaml.cs中引用我们创建好的样式文件,这样MainPage.xaml就可以使用该外部样式文件里面的样式了。

 <Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

接着创建菜单项的Model,创建一个类Scenario:

 public class Scenario
{
public string Title { get; set; }
public Type ClassType { get; set; }
}

然后在MainPage.xaml.cs中实现跳转的逻辑:

 public sealed partial class MainPage : Page
{
public static MainPage Current;
public const string FEATURE_NAME = "User Consent Verifier"; List<Scenario> scenarios = new List<Scenario>
{
new Scenario() { Title="Check Consent Availability", ClassType=typeof(Scenario1_CheckConsentAvailability)},
new Scenario() { Title="Request Consent", ClassType=typeof(Scenario2_RequestConsent)}
}; public MainPage()
{
this.InitializeComponent();
Current = this;
SampleTitle.Text = FEATURE_NAME;
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
ScenarioControl.ItemsSource = scenarios;
if (Window.Current.Bounds.Width < )
{
ScenarioControl.SelectedIndex = -;
}
else
{
ScenarioControl.SelectedIndex = ;
}
} private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NotifyUser(String.Empty, NotifyType.StatusMessage); ListBox scenarioListBox = sender as ListBox;
Scenario s = scenarioListBox.SelectedItem as Scenario;
if (s != null)
{
ScenarioFrame.Navigate(s.ClassType);
if (Window.Current.Bounds.Width < )
{
Splitter.IsPaneOpen = false;
StatusBorder.Visibility = Visibility.Collapsed;
}
}
} public List<Scenario> Scenarios
{
get { return this.scenarios; }
} public void NotifyUser(string strMessage, NotifyType type)
{
switch (type)
{
case NotifyType.StatusMessage:
StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
break;
case NotifyType.ErrorMessage:
StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
break;
}
StatusBlock.Text = strMessage;
StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
} private void Button_Click(object sender, RoutedEventArgs e)
{
Splitter.IsPaneOpen = (Splitter.IsPaneOpen == true) ? false : true;
StatusBorder.Visibility = Visibility.Collapsed;
}
}
public enum NotifyType
{
StatusMessage,
ErrorMessage
}; public class ScenarioBindingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Scenario s = value as Scenario;
return (MainPage.Current.Scenarios.IndexOf(s) + ) + ") " + s.Title;
} public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return true;
}
}

至此,首页已经完工,一个带有汉堡包菜单的主页,然后我们创建检测用户身份验证器是否可用的页面Scenario1_CheckConsentAvailability.xaml,前台代码如下:

 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="RootGrid" Margin="12,20,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,10">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
检测用户的身份验证器是否可以使用
</TextBlock>
</StackPanel> <ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" Grid.Row="1">
<Button x:Name="CheckAvailability" Content="Check Availability" Margin="0,0,10,0" Click="CheckAvailability_Click"/>
</StackPanel>
</StackPanel>
</ScrollViewer> <Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
<TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
</Grid>
</Grid>

后台实现检测用户身份验证器是否可用的代码:

     private async void CheckAvailability_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
b.IsEnabled = false;
try
{
UserConsentVerifierAvailability consentAvailability = await Windows.Security.Credentials.UI.UserConsentVerifier.CheckAvailabilityAsync();
switch (consentAvailability)
{
case UserConsentVerifierAvailability.Available:
{
rootPage.NotifyUser("用户身份验证器可用", NotifyType.StatusMessage);
break;
} case UserConsentVerifierAvailability.DeviceBusy:
{
rootPage.NotifyUser("验证器正忙或不可用", NotifyType.ErrorMessage);
break;
} case UserConsentVerifierAvailability.DeviceNotPresent:
{
rootPage.NotifyUser("没有发现验证设备", NotifyType.ErrorMessage);
break;
} case UserConsentVerifierAvailability.DisabledByPolicy:
{
rootPage.NotifyUser("策略组禁用了生物验证", NotifyType.ErrorMessage);
break;
} case UserConsentVerifierAvailability.NotConfiguredForUser:
{
rootPage.NotifyUser("该用户没有配置验证信息", NotifyType.ErrorMessage);
break;
} default:
{
rootPage.NotifyUser("验证器不可用", NotifyType.ErrorMessage);
break;
}
}
}
catch (Exception ex)
{
rootPage.NotifyUser("验证器出错了, Exception: " + ex.ToString(), NotifyType.ErrorMessage);
}
finally
{
b.IsEnabled = true;
}
}

验证页面完毕,创建请求身份验证的页面Scenario2_RequestConsent.xaml,前台代码如下:

 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="RootGrid" Margin="12,20,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,10">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
请求身份验证并发送一个消息给用户
</TextBlock>
</StackPanel> <ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel Orientation="Vertical" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Text="Message:" VerticalAlignment="Center" Width="85"/>
<TextBox x:Name="Message" Text="Message to user" Width="300"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Button x:Name="RequestConsent" Content="Request Consent" Margin="85,0,0,0" Click="RequestConsent_Click"/>
</StackPanel>
</StackPanel>
</ScrollViewer> <Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
<TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
</Grid>
</Grid>

后台请求验证的代码:

 private async void RequestConsent_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
b.IsEnabled = false; if (!String.IsNullOrEmpty(Message.Text))
{
try
{
UserConsentVerificationResult consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(Message.Text);
switch (consentResult)
{
case UserConsentVerificationResult.Verified:
{
rootPage.NotifyUser("用户已通过验证", NotifyType.StatusMessage);
break;
} case UserConsentVerificationResult.DeviceBusy:
{
rootPage.NotifyUser("验证器正在忙或者不可用", NotifyType.ErrorMessage);
break;
} case UserConsentVerificationResult.DeviceNotPresent:
{
rootPage.NotifyUser("没有发现验证设备", NotifyType.ErrorMessage);
break;
} case UserConsentVerificationResult.DisabledByPolicy:
{
rootPage.NotifyUser("策略组禁用了生物验证", NotifyType.ErrorMessage);
break;
} case UserConsentVerificationResult.NotConfiguredForUser:
{
rootPage.NotifyUser("该用户没有配置验证信息", NotifyType.ErrorMessage);
break;
} case UserConsentVerificationResult.RetriesExhausted:
{
rootPage.NotifyUser("经过10次失败的验证后,没有经过验证", NotifyType.ErrorMessage);
break;
}
case UserConsentVerificationResult.Canceled:
{
rootPage.NotifyUser("取消验证", NotifyType.ErrorMessage);
break;
} default:
{
rootPage.NotifyUser("不可用", NotifyType.ErrorMessage);
break;
}
}
}
catch (Exception ex)
{
rootPage.NotifyUser("调用身份验证器出错, Exception: " + ex.ToString(), NotifyType.ErrorMessage);
}
finally
{
b.IsEnabled = true;
}
}
else
{
rootPage.NotifyUser("文本框值为空", NotifyType.ErrorMessage);
b.IsEnabled = true;
}
}

Ok,来看下效果:

UWP/Win10新特性系列—UserConsentVerifier

推荐一个UWP开发群:53078485 大家可以进来一起学习~~

UWP/Win10新特性系列—UserConsentVerifier的更多相关文章

  1. UWP&sol;Win10新特性系列—App Service

    Win10中,新增了一个很实用的新特性叫做App Service,App Service允许App不在前台运行的情况下提供出一个或多个对外服务供其他App使用,这看起来就好像Web开发中的Web Ap ...

  2. UWP&sol;Win10新特性系列—Drag&amp&semi;Drop 拖动打开文件

    在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版 ...

  3. ArcGIS Server 10&period;1新特性系列---动态图层

    ArcGIS Server 10.1新特性里面有几个新功能是非常棒的,其中有一个就是动态图层.动态图层不是一种新发明的图层,而是说在arcgis server的web应用中可以动态的配置其渲染和内容功 ...

  4. 【转】Win10&sol;UWP新特性系列—Web

    Internet Explorer Internet Explorer 在Windows 10 升级为Edge模式,是一种交互性和兼容性都很强的新型浏览器,该浏览器相比以前的版本更新了超过2000个操 ...

  5. Win10&sol;UWP新特性系列—Launcher实现应用间的通信

    UWP中,微软为Windows.System.Launcher启动器新增了很多的功能,以前只能启动App,打开指定扩展名文件,对uri协议的解析,以及当启动的应用没有安装时则会提示前往商店下载等. 如 ...

  6. Win10&sol;UWP新特性系列—使用打印机

    微软在Win10时代终于完成的设备系统的大统一,"56个民族,56支花……"(⊙o⊙)…,既然统一了,那么也就意味着API也统一了,所以在UWP中,我们就可以使用统一的打印API来 ...

  7. Win10&sol;UWP新特性系列-GetPublisherCacheFolder

    微软Windows Runtime App拥有很强的安全模型来防止不同App之间的数据获取和共享,也就是我们所说的"沙盒机制",每个App都运行在Windows沙盒中,App之间的 ...

  8. Win10&sol;UWP新特性系列—电池报告

    UWP中,新增了当节电模式开启时,App能获取到通知的API,通过响应电源条件的更改,比如咨询用户是否使用黑色背景等来帮助延长电池使用时间. 通过Windows.Devices.Power命名空间中的 ...

  9. win10新特性,ubuntu子系统(安装及配置)

    最新版win10下可以直接跑ubuntu镜像,直接入正题. 这里如果你没有可能是你的版本不是最新的,我这里是最新的win10直接是有这个功能的.勾选后会要求重启,确定即可. 然后win键弹出搜索,输入 ...

随机推荐

  1. 诺基亚远去,《惊奇UCD》带你重塑用户体验

    我所说的成功的用户体验,是指我见过或听说过大量的用户非常喜爱我为手机行业做出的那些贡献.我的职业幸福感并不取决于我的经理或CEO说了什么,而是取决于我从实际用户那里听到了什么.             ...

  2. 各浏览器Iframe对contentWindow、contentDocument、document及frames属性测试

    Iframe易于嵌套及管理页面,但经常遇到跨域.父子页面访问问题,对于子页面访问父页面可以兼容性地通过window.Top或window.Parent或window.frameElement等操作,但 ...

  3. 删除xcode中的描述文件的路径

    打开Finder  commend + shift +g 进入文件夹  : ~/Library/MobileDevice/Provisioning Profiles  删除即可

  4. C&num;开发规范总结(个人建议)

    .NET开发编程规范 章程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的&quot ...

  5. SQL分布式查询、跨数据库查询

    --[方法1]连接服务器方法 --step1 创建链接服务器  exec sp_addlinkedserver     'srv_lnk','','SQLOLEDB', 'ip地址'  exec sp ...

  6. USB HID描述符【转】

    本文转载自: USB是个通用的总线,端口都是统一的.但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的设备的呢?这就要依赖于描述符了.USB的描述符主要有 ...

  7. 如何配置LCD背光和LED,调试方法

    LCD背光和LED配置文件 alps/custom/<proj name>lk/cust_leds.c alps/custom/<proj name>/kernel/leds/ ...

  8. PHP安装BCMath扩展

    我们都知道,大多数编程语言对于浮点型数据格式遵循 IEEE 754 标准,PHP也不例外,这就会导致在使用浮点数运算的过程中会有精度丢失的问题.PHP提供了BCMath库来支持更加精确的计算.但是我的 ...

  9. 移动端利用-webkit-box水平垂直居中&lpar;旧弹性盒&rpar;

    新弹性盒水平垂直居中参考:http://www.cnblogs.com/ooo0/p/7562884.html 新旧弹性盒样式参考:http://www.cnblogs.com/ooo0/p/7562 ...

  10. POJ K-th Number

    [题解] 数据结构采用线段树.通过将数组的每一段归并排序来建树.将数组排序来实现离散化. 时间复杂度分析:建树的过程就是归并排序,其时间复杂度为O(nlog(n)).查询时:二分查找第k小元素的复杂度 ...