首页 > 技术文章 > UWP/Win10新特性系列—UserConsentVerifier

Aran-Wang 2015-09-17 13:54 原文

    在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

 1 <Page.Resources>
 2             <local:ScenarioBindingConverter x:Key="ScenarioConverter"></local:ScenarioBindingConverter>
 3         </Page.Resources>
 4  
 5      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 6         <Grid.ColumnDefinitions>
 7             <ColumnDefinition Width="Auto"/>
 8             <ColumnDefinition Width="*"/>
 9         </Grid.ColumnDefinitions>
10         <VisualStateManager.VisualStateGroups>
11             <VisualStateGroup>
12                 <VisualState x:Name="wideState">
13                     <VisualState.StateTriggers>
14                         <AdaptiveTrigger MinWindowWidth="641" />
15                     </VisualState.StateTriggers>
16                     <VisualState.Setters>
17                         <Setter Target="Splitter.DisplayMode" Value="Inline"/>
18                     </VisualState.Setters>
19                 </VisualState>
20                 <VisualState x:Name="narrowState">
21                     <VisualState.StateTriggers>
22                         <AdaptiveTrigger MinWindowWidth="0" />
23                     </VisualState.StateTriggers>
24                     <VisualState.Setters>
25                         <Setter Target="Splitter.DisplayMode" Value="Overlay"/>
26                     </VisualState.Setters>
27                 </VisualState>
28             </VisualStateGroup>
29         </VisualStateManager.VisualStateGroups>
30         <SplitView x:Name="Splitter" IsPaneOpen="True" Grid.Column="1">
31             <SplitView.Pane>
32                 <RelativePanel Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
33                     <StackPanel x:Name="HeaderPanel" Orientation="Horizontal">
34                         <TextBlock x:Name="Header" Text="Windows 10 sample" Style="{StaticResource TagLineTextStyle}" Margin="0,15,0,0" />
35                     </StackPanel>
36                     <TextBlock x:Name="SampleTitle" Text="Sample Title Here" Style="{StaticResource SampleHeaderTextStyle}" TextWrapping="Wrap" RelativePanel.Below="HeaderPanel" Margin="0,10,0,0"/>
37                     <ListBox x:Name="ScenarioControl" SelectionChanged="ScenarioControl_SelectionChanged"
38                  SelectionMode="Single" HorizontalAlignment="Left" Style="{StaticResource ScenarioListBoxStyle}"
39                  VerticalAlignment="Top" RelativePanel.Below="SampleTitle" Margin="0,10,0,0" >
40                         <ListBox.ItemTemplate>
41                             <DataTemplate>
42                                 <TextBlock Text="{Binding Converter={StaticResource ScenarioConverter}}" Style="{StaticResource ListItemTextStyle}"/>
43                             </DataTemplate>
44                         </ListBox.ItemTemplate>
45                     </ListBox>
46                 </RelativePanel>
47             </SplitView.Pane>
48             <RelativePanel>
49                 <Frame x:Name="ScenarioFrame" Margin="0,5,0,0" RelativePanel.AlignTopWithPanel="True" RelativePanel.Above="StatusPanel"/>
50                 <StackPanel x:Name="StatusPanel" Orientation="Vertical" RelativePanel.AlignBottomWithPanel="True">
51                     <TextBlock x:Name="StatusLabel" Margin="0,0,0,10" TextWrapping="Wrap" Text="Status:" />
52                     <Border x:Name="StatusBorder" Margin="0,0,0,0" Visibility="Collapsed" >
53                         <TextBlock x:Name="StatusBlock" FontWeight="Bold" MaxHeight="200" MinWidth="{Binding ElementName=Splitter, Path=ActualWidth}" TextTrimming="CharacterEllipsis"  Margin="20,10,10,20" TextWrapping="Wrap"/>
54                     </Border>
55                 </StackPanel>
56             </RelativePanel>
57         </SplitView>
58         <Border Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}">
59             <ToggleButton Style="{StaticResource SymbolButton}" Click="Button_Click" VerticalAlignment="Top" Foreground="{ThemeResource ApplicationForegroundThemeBrush}">
60                 <ToggleButton.Content>
61                     <FontIcon x:Name="Hamburger" FontFamily="Segoe MDL2 Assets" Glyph="&#xE700;" Margin="0,10,0,0"/>
62                 </ToggleButton.Content>
63             </ToggleButton>
64         </Border>
65 </Grid>

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

  1 <Style x:Key="SymbolButton" TargetType="ToggleButton">
  2       <Setter Property="Background" Value="{ThemeResource ToggleButtonBackgroundThemeBrush}"/>
  3       <Setter Property="Foreground" Value="{ThemeResource ToggleButtonForegroundThemeBrush}"/>
  4       <Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderThemeBrush}"/>
  5       <Setter Property="BorderThickness" Value="{ThemeResource ToggleButtonBorderThemeThickness}"/>
  6       <Setter Property="Padding" Value="12,4,12,5"/>
  7       <Setter Property="HorizontalAlignment" Value="Left"/>
  8       <Setter Property="VerticalAlignment" Value="Center"/>
  9       <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
 10       <Setter Property="FontWeight" Value="SemiBold"/>
 11       <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
 12       <Setter Property="Template">
 13           <Setter.Value>
 14               <ControlTemplate TargetType="ToggleButton">
 15                   <Grid>
 16                       <VisualStateManager.VisualStateGroups>
 17                           <VisualStateGroup x:Name="CommonStates">
 18                               <VisualState x:Name="Normal"/>
 19                               <VisualState x:Name="PointerOver">
 20                                   <Storyboard>
 21                                   </Storyboard>
 22                               </VisualState>
 23                               <VisualState x:Name="Pressed">
 24                                   <Storyboard>
 25                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 26                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBackgroundThemeBrush}"/>
 27                                       </ObjectAnimationUsingKeyFrames>
 28                                   </Storyboard>
 29                               </VisualState>
 30                               <VisualState x:Name="Disabled">
 31                                   <Storyboard>
 32                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 33                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}"/>
 34                                       </ObjectAnimationUsingKeyFrames>
 35                                   </Storyboard>
 36                               </VisualState>
 37                               <VisualState x:Name="Checked">
 38                                   <Storyboard>
 39                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 40                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedBackgroundThemeBrush}"/>
 41                                       </ObjectAnimationUsingKeyFrames>
 42                                   </Storyboard>
 43                               </VisualState>
 44                               <VisualState x:Name="CheckedPointerOver">
 45                                   <Storyboard>
 46                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 47                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPointerOverBackgroundThemeBrush}"/>
 48                                       </ObjectAnimationUsingKeyFrames>
 49                                   </Storyboard>
 50                               </VisualState>
 51                               <VisualState x:Name="CheckedPressed">
 52                                   <Storyboard>
 53                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 54                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedPressedBackgroundThemeBrush}"/>
 55                                       </ObjectAnimationUsingKeyFrames>
 56                                   </Storyboard>
 57                               </VisualState>
 58                               <VisualState x:Name="CheckedDisabled">
 59                                   <Storyboard>
 60                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 61                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonCheckedDisabledForegroundThemeBrush}"/>
 62                                       </ObjectAnimationUsingKeyFrames>
 63                                   </Storyboard>
 64                               </VisualState>
 65                               <VisualState x:Name="Indeterminate"/>
 66                               <VisualState x:Name="IndeterminatePointerOver">
 67                               </VisualState>
 68                               <VisualState x:Name="IndeterminatePressed">
 69                                   <Storyboard>
 70                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 71                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonPressedForegroundThemeBrush}"/>
 72                                       </ObjectAnimationUsingKeyFrames>
 73                                   </Storyboard>
 74                               </VisualState>
 75                               <VisualState x:Name="IndeterminateDisabled">
 76                                   <Storyboard>
 77                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
 78                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonDisabledForegroundThemeBrush}"/>
 79                                       </ObjectAnimationUsingKeyFrames>
 80                                   </Storyboard>
 81                               </VisualState>
 82                           </VisualStateGroup>
 83                           <VisualStateGroup x:Name="FocusStates">
 84                               <VisualState x:Name="Focused">
 85                                   <Storyboard>
 86                                       <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualWhite"/>
 87                                       <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualBlack"/>
 88                                   </Storyboard>
 89                               </VisualState>
 90                               <VisualState x:Name="Unfocused"/>
 91                               <VisualState x:Name="PointerFocused"/>
 92                           </VisualStateGroup>
 93                       </VisualStateManager.VisualStateGroups>
 94                       <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}"/>
 95                       <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="1.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" StrokeDashArray="1,1"/>
 96                       <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="0.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}" StrokeDashArray="1,1"/>
 97                   </Grid>
 98               </ControlTemplate>
 99           </Setter.Value>
100       </Setter>
101   </Style>
102  
103   <Style x:Key="BasicTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
104       <Setter Property="FontWeight" Value="Normal"/>
105       <Setter Property="Margin" Value="0,0,0,10"/>
106   </Style>
107  
108   <Style x:Key="TagLineTextStyle" TargetType="TextBlock">
109       <Setter Property="FontFamily" Value="Segoe UI Light"/>
110       <Setter Property="FontSize" Value="16"/>
111   </Style>
112  
113   <Style x:Key="SampleHeaderTextStyle" TargetType="TextBlock">
114       <Setter Property="FontFamily" Value="Segoe UI Light"/>
115       <Setter Property="FontSize" Value="26.667"/>
116   </Style>
117  
118   <Style x:Key="ListItemTextStyle" TargetType="TextBlock">
119       <Setter Property="FontFamily" Value="Segoe UI Semilight"/>
120       <Setter Property="FontSize" Value="18"/>
121       <Setter Property="Margin" Value="10,0,0,0"/>
122       <Setter Property="Foreground" Value="White"/>
123       <Setter Property="TextWrapping" Value="Wrap"/>
124   </Style>
125  
126   <Style x:Key="CopyrightTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
127       <Setter Property="FontWeight" Value="Normal"/>
128   </Style>
129  
130   <Style x:Key="ScenarioHeaderTextStyle" TargetType="TextBlock">
131       <Setter Property="FontFamily" Value="Segoe UI Light"/>
132       <Setter Property="FontSize" Value="26.667"/>
133   </Style>
134  
135   <Style x:Key="ScenarioDescriptionTextStyle" TargetType="TextBlock">
136       <Setter Property="FontFamily" Value="Segoe UI Light"/>
137       <Setter Property="FontSize" Value="16"/>
138   </Style>
139  
140   <Style x:Key="BaseMessageStyle" TargetType="TextBlock">
141       <Setter Property="FontFamily" Value="Segoe UI Semilight"/>
142       <Setter Property="FontSize" Value="14.667"/>
143       <Setter Property="Margin" Value="0,0,0,5"/>
144   </Style>
145  
146   <Style x:Key="SeparatorStyle" TargetType="TextBlock">
147       <Setter Property="FontFamily" Value="Segoe UI"/>
148       <Setter Property="FontSize" Value="9"/>
149       <Setter Property="Foreground" Value="Gray"/>
150   </Style>
151  
152   <Style x:Key="HyperlinkStyle" TargetType="HyperlinkButton">
153       <Setter Property="Padding" Value="1"/>
154       <Setter Property="Foreground" Value="Gray"/>
155   </Style>
156  
157   <!-- Default style for Windows.UI.Xaml.Controls.ListBoxItem -->
158   <Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
159       <Setter Property="Background" Value="Transparent" />
160       <Setter Property="TabNavigation" Value="Local" />
161       <Setter Property="Padding" Value="8,10" />
162       <Setter Property="HorizontalContentAlignment" Value="Left" />
163       <Setter Property="Template">
164           <Setter.Value>
165               <ControlTemplate TargetType="ListBoxItem">
166                   <Border x:Name="LayoutRoot"
167                       Background="{TemplateBinding Background}"
168                       BorderBrush="{TemplateBinding BorderBrush}"
169                       BorderThickness="{TemplateBinding BorderThickness}">
170                       <VisualStateManager.VisualStateGroups>
171                           <VisualStateGroup x:Name="CommonStates">
172                               <VisualState x:Name="Normal" />
173                               <VisualState x:Name="PointerOver">
174                                   <Storyboard>
175                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot"
176                                                                  Storyboard.TargetProperty="Background">
177                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPointerOverBackgroundThemeBrush}" />
178                                       </ObjectAnimationUsingKeyFrames>
179                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
180                                                                  Storyboard.TargetProperty="Foreground">
181                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPointerOverForegroundThemeBrush}" />
182                                       </ObjectAnimationUsingKeyFrames>
183                                   </Storyboard>
184                               </VisualState>
185                               <VisualState x:Name="Disabled">
186                                   <Storyboard>
187                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot"
188                                                                  Storyboard.TargetProperty="Background">
189                                           <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
190                                       </ObjectAnimationUsingKeyFrames>
191                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
192                                                                  Storyboard.TargetProperty="Foreground">
193                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemDisabledForegroundThemeBrush}" />
194                                       </ObjectAnimationUsingKeyFrames>
195                                   </Storyboard>
196                               </VisualState>
197                               <VisualState x:Name="Pressed">
198                                   <Storyboard>
199                                       <DoubleAnimation Storyboard.TargetName="PressedBackground"
200                                                    Storyboard.TargetProperty="Opacity"
201                                                    To="1"
202                                                    Duration="0" />
203                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
204                                                                  Storyboard.TargetProperty="Foreground">
205                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemPressedForegroundThemeBrush}" />
206                                       </ObjectAnimationUsingKeyFrames>
207                                   </Storyboard>
208                               </VisualState>
209                           </VisualStateGroup>
210                           <VisualStateGroup x:Name="SelectionStates">
211                               <VisualState x:Name="Unselected" />
212                               <VisualState x:Name="Selected">
213                                   <Storyboard>
214                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
215                                                                  Storyboard.TargetProperty="Background">
216                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
217                                       </ObjectAnimationUsingKeyFrames>
218                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
219                                                                  Storyboard.TargetProperty="Foreground">
220                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
221                                       </ObjectAnimationUsingKeyFrames>
222                                   </Storyboard>
223                               </VisualState>
224                               <VisualState x:Name="SelectedUnfocused">
225                                   <Storyboard>
226                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
227                                                                  Storyboard.TargetProperty="Background">
228                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
229                                       </ObjectAnimationUsingKeyFrames>
230                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
231                                                                  Storyboard.TargetProperty="Foreground">
232                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
233                                       </ObjectAnimationUsingKeyFrames>
234                                   </Storyboard>
235                               </VisualState>
236                               <VisualState x:Name="SelectedDisabled">
237                                   <Storyboard>
238                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
239                                                                  Storyboard.TargetProperty="Background">
240                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedDisabledBackgroundThemeBrush}" />
241                                       </ObjectAnimationUsingKeyFrames>
242                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
243                                                                  Storyboard.TargetProperty="Foreground">
244                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedDisabledForegroundThemeBrush}" />
245                                       </ObjectAnimationUsingKeyFrames>
246                                   </Storyboard>
247                               </VisualState>
248                               <VisualState x:Name="SelectedPointerOver">
249                                   <Storyboard>
250                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
251                                                                  Storyboard.TargetProperty="Background">
252                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedPointerOverBackgroundThemeBrush}" />
253                                       </ObjectAnimationUsingKeyFrames>
254                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
255                                                                  Storyboard.TargetProperty="Foreground">
256                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
257                                       </ObjectAnimationUsingKeyFrames>
258                                   </Storyboard>
259                               </VisualState>
260                               <VisualState x:Name="SelectedPressed">
261                                   <Storyboard>
262                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InnerGrid"
263                                                                  Storyboard.TargetProperty="Background">
264                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedBackgroundThemeBrush}" />
265                                       </ObjectAnimationUsingKeyFrames>
266                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
267                                                                  Storyboard.TargetProperty="Foreground">
268                                           <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ListBoxItemSelectedForegroundThemeBrush}" />
269                                       </ObjectAnimationUsingKeyFrames>
270                                   </Storyboard>
271                               </VisualState>
272                           </VisualStateGroup>
273                           <VisualStateGroup x:Name="FocusStates">
274                               <VisualState x:Name="Focused">
275                                   <Storyboard>
276                                       <DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
277                                                    Storyboard.TargetProperty="Opacity"
278                                                    To="1"
279                                                    Duration="0" />
280                                       <DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
281                                                    Storyboard.TargetProperty="Opacity"
282                                                    To="1"
283                                                    Duration="0" />
284                                   </Storyboard>
285                               </VisualState>
286                               <VisualState x:Name="Unfocused" />
287                               <VisualState x:Name="PointerFocused" />
288                           </VisualStateGroup>
289                       </VisualStateManager.VisualStateGroups>
290                       <Grid x:Name="InnerGrid"
291                         Background="Transparent">
292                           <Rectangle x:Name="PressedBackground"
293                                  Fill="{ThemeResource ListBoxItemPressedBackgroundThemeBrush}"
294                                  Opacity="0" />
295                           <ContentPresenter x:Name="ContentPresenter"
296                                         Content="{TemplateBinding Content}"
297                                         ContentTransitions="{TemplateBinding ContentTransitions}"
298                                         ContentTemplate="{TemplateBinding ContentTemplate}"
299                                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
300                                         VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
301                                         Margin="{TemplateBinding Padding}" />
302                           <Rectangle x:Name="FocusVisualWhite"
303                                  Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
304                                  StrokeEndLineCap="Square"
305                                  StrokeDashArray="1,1"
306                                  Opacity="0"
307                                  StrokeDashOffset=".5" />
308                           <Rectangle x:Name="FocusVisualBlack"
309                                  Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
310                                  StrokeEndLineCap="Square"
311                                  StrokeDashArray="1,1"
312                                  Opacity="0"
313                                  StrokeDashOffset="1.5" />
314                       </Grid>
315                   </Border>
316               </ControlTemplate>
317           </Setter.Value>
318       </Setter>
319   </Style>
320  
321  
322   <Style x:Key="ScenarioListBoxStyle" TargetType="ListBox">
323       <Setter Property="Foreground" Value="{ThemeResource ListBoxForegroundThemeBrush}"/>
324       <Setter Property="Background" Value="Transparent"/>
325       <Setter Property="BorderBrush" Value="Transparent"/>
326       <Setter Property="BorderThickness" Value="{ThemeResource ListBoxBorderThemeThickness}"/>
327       <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
328       <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
329       <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
330       <Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="True"/>
331       <Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled"/>
332       <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True"/>
333       <Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
334       <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
335       <Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
336       <Setter Property="IsTabStop" Value="False"/>
337       <Setter Property="TabNavigation" Value="Once"/>
338       <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
339       <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
340       <Setter Property="ItemsPanel">
341           <Setter.Value>
342               <ItemsPanelTemplate>
343                   <VirtualizingStackPanel Background="Transparent"/>
344               </ItemsPanelTemplate>
345           </Setter.Value>
346       </Setter>
347       <Setter Property="Template">
348           <Setter.Value>
349               <ControlTemplate TargetType="ListBox">
350                   <Border x:Name="LayoutRoot" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent">
351                       <VisualStateManager.VisualStateGroups>
352                           <VisualStateGroup x:Name="CommonStates">
353                               <VisualState x:Name="Normal"/>
354                               <VisualState x:Name="Disabled">
355                                   <Storyboard>
356                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
357                                           <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
358                                       </ObjectAnimationUsingKeyFrames>
359                                   </Storyboard>
360                               </VisualState>
361                           </VisualStateGroup>
362                           <VisualStateGroup x:Name="FocusStates">
363                               <VisualState x:Name="Focused">
364                                   <Storyboard>
365                                       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
366                                           <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
367                                       </ObjectAnimationUsingKeyFrames>
368                                   </Storyboard>
369                               </VisualState>
370                               <VisualState x:Name="Unfocused"/>
371                           </VisualStateGroup>
372                       </VisualStateManager.VisualStateGroups>
373                       <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}">
374                           <ItemsPresenter/>
375                       </ScrollViewer>
376                   </Border>
377               </ControlTemplate>
378           </Setter.Value>
379       </Setter>
380   </Style>

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

1 <Application.Resources>
2        <ResourceDictionary>
3            <ResourceDictionary.MergedDictionaries>
4                <ResourceDictionary Source="/Styles/Styles.xaml"/>
5            </ResourceDictionary.MergedDictionaries>
6        </ResourceDictionary>
7    </Application.Resources>

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

1 public class Scenario
2 {
3     public string Title { get; set; }
4     public Type ClassType { get; set; }
5 }

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

 1 public sealed partial class MainPage : Page
 2     {
 3         public static MainPage Current;
 4         public const string FEATURE_NAME = "User Consent Verifier";
 5  
 6         List<Scenario> scenarios = new List<Scenario>
 7         {
 8             new Scenario() { Title="Check Consent Availability", ClassType=typeof(Scenario1_CheckConsentAvailability)},
 9             new Scenario() { Title="Request Consent", ClassType=typeof(Scenario2_RequestConsent)}
10         };
11  
12         public MainPage()
13         {
14             this.InitializeComponent();
15             Current = this;
16             SampleTitle.Text = FEATURE_NAME;
17         }
18  
19         protected override void OnNavigatedTo(NavigationEventArgs e)
20         {
21             ScenarioControl.ItemsSource = scenarios;
22             if (Window.Current.Bounds.Width < 640)
23             {
24                 ScenarioControl.SelectedIndex = -1;
25             }
26             else
27             {
28                 ScenarioControl.SelectedIndex = 0;
29             }
30         }
31  
32         private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
33         {
34             NotifyUser(String.Empty, NotifyType.StatusMessage);
35  
36             ListBox scenarioListBox = sender as ListBox;
37             Scenario s = scenarioListBox.SelectedItem as Scenario;
38             if (s != null)
39             {
40                 ScenarioFrame.Navigate(s.ClassType);
41                 if (Window.Current.Bounds.Width < 640)
42                 {
43                     Splitter.IsPaneOpen = false;
44                     StatusBorder.Visibility = Visibility.Collapsed;
45                 }
46             }
47         }
48  
49         public List<Scenario> Scenarios
50         {
51             get { return this.scenarios; }
52         }
53  
54         public void NotifyUser(string strMessage, NotifyType type)
55         {
56             switch (type)
57             {
58                 case NotifyType.StatusMessage:
59                     StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
60                     break;
61                 case NotifyType.ErrorMessage:
62                     StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
63                     break;
64             }
65             StatusBlock.Text = strMessage;
66             StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
67         }
68  
69         private void Button_Click(object sender, RoutedEventArgs e)
70         {
71             Splitter.IsPaneOpen = (Splitter.IsPaneOpen == true) ? false : true;
72             StatusBorder.Visibility = Visibility.Collapsed;
73         }
74     }
75     public enum NotifyType
76     {
77         StatusMessage,
78         ErrorMessage
79     };
80  
81     public class ScenarioBindingConverter : IValueConverter
82     {
83         public object Convert(object value, Type targetType, object parameter, string language)
84         {
85             Scenario s = value as Scenario;
86             return (MainPage.Current.Scenarios.IndexOf(s) + 1) + ") " + s.Title;
87         }
88  
89         public object ConvertBack(object value, Type targetType, object parameter, string language)
90         {
91             return true;
92         }
93 }

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

 1 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 2         <Grid x:Name="RootGrid" Margin="12,20,12,12">
 3             <Grid.RowDefinitions>
 4                 <RowDefinition Height="Auto"/>
 5                 <RowDefinition Height="*"/>
 6                 <RowDefinition Height="Auto"/>
 7             </Grid.RowDefinitions>
 8             <StackPanel Margin="0,0,0,10">
 9                 <TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
10                 <TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
11                     检测用户的身份验证器是否可以使用
12                 </TextBlock>
13             </StackPanel>
14  
15             <ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
16                 <StackPanel Orientation="Vertical" VerticalAlignment="Top">
17                     <StackPanel Orientation="Horizontal" Margin="0,10,0,0" Grid.Row="1">
18                         <Button x:Name="CheckAvailability" Content="Check Availability" Margin="0,0,10,0" Click="CheckAvailability_Click"/>
19                     </StackPanel>
20                 </StackPanel>
21             </ScrollViewer>
22  
23             <Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
24             <TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
25         </Grid>
26     </Grid>

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

 1     private async void CheckAvailability_Click(object sender, RoutedEventArgs e)
 2       {
 3           Button b = sender as Button;
 4           b.IsEnabled = false;
 5           try
 6           {
 7               UserConsentVerifierAvailability consentAvailability = await Windows.Security.Credentials.UI.UserConsentVerifier.CheckAvailabilityAsync();
 8               switch (consentAvailability)
 9               {
10                   case UserConsentVerifierAvailability.Available:
11                       {
12                           rootPage.NotifyUser("用户身份验证器可用", NotifyType.StatusMessage);
13                           break;
14                       }
15  
16                   case UserConsentVerifierAvailability.DeviceBusy:
17                       {
18                           rootPage.NotifyUser("验证器正忙或不可用", NotifyType.ErrorMessage);
19                           break;
20                       }
21  
22                   case UserConsentVerifierAvailability.DeviceNotPresent:
23                       {
24                           rootPage.NotifyUser("没有发现验证设备", NotifyType.ErrorMessage);
25                           break;
26                       }
27  
28                   case UserConsentVerifierAvailability.DisabledByPolicy:
29                       {
30                           rootPage.NotifyUser("策略组禁用了生物验证", NotifyType.ErrorMessage);
31                           break;
32                       }
33  
34                   case UserConsentVerifierAvailability.NotConfiguredForUser:
35                       {
36                           rootPage.NotifyUser("该用户没有配置验证信息", NotifyType.ErrorMessage);
37                           break;
38                       }
39  
40                   default:
41                       {
42                           rootPage.NotifyUser("验证器不可用", NotifyType.ErrorMessage);
43                           break;
44                       }
45               }
46           }
47           catch (Exception ex)
48           {
49               rootPage.NotifyUser("验证器出错了, Exception: " + ex.ToString(), NotifyType.ErrorMessage);
50           }
51           finally
52           {
53               b.IsEnabled = true;
54           }
55 }

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

 1 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 2        <Grid x:Name="RootGrid" Margin="12,20,12,12">
 3            <Grid.RowDefinitions>
 4                <RowDefinition Height="Auto"/>
 5                <RowDefinition Height="*"/>
 6                <RowDefinition Height="Auto"/>
 7            </Grid.RowDefinitions>
 8            <StackPanel Margin="0,0,0,10">
 9                <TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
10                <TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap">
11                    请求身份验证并发送一个消息给用户
12                </TextBlock>
13            </StackPanel>
14  
15            <ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
16                <StackPanel Orientation="Vertical" VerticalAlignment="Top">
17                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
18                        <TextBlock Text="Message:" VerticalAlignment="Center" Width="85"/>
19                        <TextBox x:Name="Message" Text="Message to user" Width="300"/>
20                    </StackPanel>
21                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
22                        <Button x:Name="RequestConsent" Content="Request Consent" Margin="85,0,0,0" Click="RequestConsent_Click"/>
23                    </StackPanel>
24                </StackPanel>
25            </ScrollViewer>
26  
27            <Border x:Name="ErrorBorder" Background="Red" Grid.Row="2"/>
28            <TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
29        </Grid>
30    </Grid>

后台请求验证的代码:

 1 private async void RequestConsent_Click(object sender, RoutedEventArgs e)
 2      {
 3          Button b = sender as Button;
 4          b.IsEnabled = false;
 5  
 6          if (!String.IsNullOrEmpty(Message.Text))
 7          {
 8              try
 9              {
10                  UserConsentVerificationResult consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(Message.Text);
11                  switch (consentResult)
12                  {
13                      case UserConsentVerificationResult.Verified:
14                          {
15                              rootPage.NotifyUser("用户已通过验证", NotifyType.StatusMessage);
16                              break;
17                          }
18  
19                      case UserConsentVerificationResult.DeviceBusy:
20                          {
21                              rootPage.NotifyUser("验证器正在忙或者不可用", NotifyType.ErrorMessage);
22                              break;
23                          }
24  
25                      case UserConsentVerificationResult.DeviceNotPresent:
26                          {
27                              rootPage.NotifyUser("没有发现验证设备", NotifyType.ErrorMessage);
28                              break;
29                          }
30  
31                      case UserConsentVerificationResult.DisabledByPolicy:
32                          {
33                              rootPage.NotifyUser("策略组禁用了生物验证", NotifyType.ErrorMessage);
34                              break;
35                          }
36  
37                      case UserConsentVerificationResult.NotConfiguredForUser:
38                          {
39                              rootPage.NotifyUser("该用户没有配置验证信息", NotifyType.ErrorMessage);
40                              break;
41                          }
42  
43                      case UserConsentVerificationResult.RetriesExhausted:
44                          {
45                              rootPage.NotifyUser("经过10次失败的验证后,没有经过验证", NotifyType.ErrorMessage);
46                              break;
47                          }
48                      case UserConsentVerificationResult.Canceled:
49                          {
50                              rootPage.NotifyUser("取消验证", NotifyType.ErrorMessage);
51                              break;
52                          }
53  
54                      default:
55                          {
56                              rootPage.NotifyUser("不可用", NotifyType.ErrorMessage);
57                              break;
58                          }
59                  }
60              }
61              catch (Exception ex)
62              {
63                  rootPage.NotifyUser("调用身份验证器出错, Exception: " + ex.ToString(), NotifyType.ErrorMessage);
64              }
65              finally
66              {
67                  b.IsEnabled = true;
68              }
69          }
70          else
71          {
72              rootPage.NotifyUser("文本框值为空", NotifyType.ErrorMessage);
73              b.IsEnabled = true;
74          }
75 }

Ok,来看下效果:

 

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

 

推荐阅读