在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="" 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 大家可以进来一起学习~~