在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开发群:53078485 大家可以进来一起学习~~

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

  1. UWP/Win10新特性系列—App Service

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

  2. UWP/Win10新特性系列—Drag&Drop 拖动打开文件

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

  3. Java8新特性系列-默认方法

    Java8 Interface Default and Static Methods 原文连接:Java8新特性系列-默认方法 – 微爱博客 在 Java 8 之前,接口只能有公共抽象方法. 如果不强 ...

  4. Java8新特性系列-Lambda

    转载自:Java8新特性系列-Lambda – 微爱博客 Lambda Expressions in Java 8 Lambda 表达式是 Java 8 最流行的特性.它们将函数式编程概念引入 Jav ...

  5. ArcGIS Server 10.1新特性系列---动态图层

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

  6. 【转】Win10/UWP新特性系列—Web

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

  7. Win10/UWP新特性系列—Launcher实现应用间的通信

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

  8. Win10/UWP新特性系列—使用打印机

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

  9. Win10/UWP新特性系列-GetPublisherCacheFolder

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

随机推荐

  1. twemproxy - Proxy Server for Redis 安装测试

    1. 安装 (1) 系统环境 测试用的服务器为阿里云ECS,4核8G,CentOS6.3 64bit. 部署了3个Redis实例,监听端口号为7410,7420,7430,设置maxmemory为25 ...

  2. oracle mysql sqlserver数据库中的分页

    oracle: select * from (select rownum r,t1.* from tablename t1 where rownum <M+N ) t2 where t2.r&g ...

  3. hadoop2.0初识1.3

    1.配置分布式hadoop 1.1 准备三台测试机(虚拟机就可以) 1.1.1 将life-hadoop虚拟机克隆2个分别为life-hadoop02和life-hadoop03 1.1.2 查看ip ...

  4. Winform开发框架之单据窗体生成(主从表,流水单号)

    源码地址:https://github.com/GarsonZhang/GZFramework.ShareDemo 前言 1.在开始本节前请先重置代码为 chapter-03-start 懒人地址:h ...

  5. GIS服务器需求分析

    一. 需求概要 1 边界 核心职责 接收并存储外部各方系统GPS数据 GPS数据实时分发, 轨迹检索   2 流程 GIS客户端向GIS服务器订购 GIS客户端向GIS服务器订购号码(仅有号码这一项业 ...

  6. iOS - Git 代码版本管理

    1.Git Git 是用 C 语言开发的分布版本控制系统.版本控制系统可以保留一个文件集合的历史记录,并能回滚文件集合到另一个状态(历史记录状态).另一个状态可以是不同的文件,也可以是不同的文件内容. ...

  7. Windows下配置Git

    1.从git官网下载windows版本的git:http://git-scm.com/downloads 2.一般使用默认设置即可:一路next,git安装完毕! 3.但是如果这时你打开windows ...

  8. JDBC连接执行MySQL存储过程报权限错误

    今天在测试项目的时候  突然就报了一个错出来. User does not have access to metadata required to determine stored procedure ...

  9. Linux 远程桌面 访问 WIndows

    1. Debain 系列 linux sudo aptitude install rdesktop 2. Connect rdesktop <hostname> -r sound:off ...

  10. CSS 3 颜色表示法

    1,Color Name:red    优点:方便记忆  缺点:数量少不支持透明度 2,HEX方式:#FFFFFF    优点:颜色种类多   缺点:换算复杂需要借助工具 3,RGB方式:rgb(25 ...