• WPF PasswordBox 明文显示的样式


    最近学习WPF,突然想做PasswordBox明文显示的样式,在网上搜索了一下,代码都有问题,不能够直接复用。所以,在同事的帮助下,做了一个明文显示样式的Demo。

    首先,创建一个WPF App的项目。

    打开MainWindow.xaml文件,代码如下:

     1 <Window x:Class="WpfApp4.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:WpfApp4"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="450" Width="800">
     9     <Grid>
    10     </Grid>
    11 </Window>
    View Code

    构建Grid布局,并创建两个控件,分别为TextBox、PasswordBox,代码如下:

    1 <Grid>
    2         <Grid.RowDefinitions>
    3             <RowDefinition Height="40"/>
    4             <RowDefinition Height="auto"/>
    5         </Grid.RowDefinitions>
    6         <TextBox x:Name="userName" Grid.Row="0" Width="200" Height="40" HorizontalAlignment="Left"></TextBox>
    7         <PasswordBox x:Name="userPwd" Grid.Row="1" Width="200" Height="40" HorizontalAlignment="Left" Style="{StaticResource PasswordBoxStyle1}" FontSize="20" VerticalAlignment="Center" local:ControlAttachProperty.PlaceHolder="请输入密码" />
    8     </Grid>
    View Code

    此时,Style="{StaticResource PasswordBoxStyle1}" 与 local:ControlAttachProperty.PlaceHolder="请输入密码" 会报错。(现在可以删掉这两句)

    现在要实现的样式效果:

    1、输入密码后,点击眼睛按钮可以显示密码明文效果。

    2、密码框为空且没有获取焦点时,显示提示文字。

    3、密码为空时,不允许点击眼睛按钮

    样式代码需要放在Window标签下Grid标签前,代码如下:

      1     <Window.Resources>
      2         <Style x:Key="FocusVisual">
      3             <Setter Property="Control.Template">
      4                 <Setter.Value>
      5                     <ControlTemplate>
      6                         <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
      7                     </ControlTemplate>
      8                 </Setter.Value>
      9             </Setter>
     10         </Style>
     11         
     12         <!--眼睛按钮的样式-->
     13         <Style TargetType="Button" x:Key="EyeButton">
     14             <Setter Property="Template">
     15                 <Setter.Value>
     16                     <ControlTemplate TargetType="Button">
     17                         <Border Background="{TemplateBinding Background}" />
     18                     </ControlTemplate>
     19                 </Setter.Value>
     20             </Setter>
     21         </Style>
     22         
     23         <!--PassWordBox样式-->
     24         <SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
     25         <SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
     26         <SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
     27         <Style x:Key="PasswordBoxStyle1" TargetType="{x:Type PasswordBox}">
     28             <Setter Property="local:PasswordBoxHelper.Attach" Value="True"/>
     29             <Setter Property="PasswordChar" Value=""/>
     30             <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
     31             <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
     32             <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
     33             <Setter Property="BorderThickness" Value="1"/>
     34             <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
     35             <Setter Property="HorizontalContentAlignment" Value="Left"/>
     36             <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
     37             <Setter Property="AllowDrop" Value="true"/>
     38             <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
     39             <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
     40             <Setter Property="Template">
     41                 <Setter.Value>
     42                     <ControlTemplate TargetType="{x:Type PasswordBox}">
     43                         <Border x:Name="border" CornerRadius="10" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
     44                             <!--重写构造PasswordBox-->
     45                             <Grid x:Name="PART_InnerGrid">
     46                                 <Grid.ColumnDefinitions>
     47                                     <ColumnDefinition/>
     48                                     <ColumnDefinition Width="Auto"/>
     49                                 </Grid.ColumnDefinitions>
     50                                 <!--PasswordBox原有的显示节点-->
     51                                 <ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" IsTabStop="False" VerticalAlignment="Stretch" Background="{x:Null}" VerticalContentAlignment="Center" Margin="5,5"/>
     52                                 <!--创建明文显示的TextBox-->
     53                                 <TextBox x:Name="PART_PasswordShower"  BorderBrush="Transparent" Text="{Binding Path=(local:PasswordBoxHelper.Password),RelativeSource={RelativeSource TemplatedParent}}" BorderThickness="0" Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="5,5"/>
     54                                 <!--创建提示字符-->
     55                                 <TextBlock x:Name="PART_PlaceHolder" Text="{Binding Path=(local:ControlAttachProperty.PlaceHolder),RelativeSource={RelativeSource TemplatedParent}}"  Visibility="Collapsed" Opacity="0.6" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,5"/>
     56                                 <!--触发按钮显示样式-->
     57                                 <Button x:Name="PART_ToggleEye" Grid.Column="1" Width="40"  Margin="3,3" BorderThickness="0" Style="{StaticResource EyeButton}" >
     58                                     <Button.Background>
     59                                         <ImageBrush x:Name="img_eye" ImageSource="eye_slash.png"/>
     60                                     </Button.Background>
     61                                 </Button>
     62                             </Grid>
     63                         </Border>
     64                         <ControlTemplate.Triggers>
     65                             <Trigger Property="IsEnabled" Value="false">
     66                                 <Setter Property="Opacity" TargetName="border" Value="0.56"/>
     67                             </Trigger>
     68                             <Trigger Property="IsMouseOver" Value="true">
     69                                 <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
     70                             </Trigger>
     71                             <Trigger Property="IsKeyboardFocused" Value="true">
     72                                 <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
     73                             </Trigger>
     74                             <!--密码框为空设置按钮禁用-->
     75                             <Trigger Property="local:PasswordBoxHelper.Password"  Value="">
     76                                 <Setter TargetName="PART_ToggleEye" Property="IsEnabled" Value="False"/>
     77                             </Trigger>
     78                             <!--按住按钮,更改按钮背景图片并设置明文框显示且密码框不显示且不占用-->
     79                             <Trigger Property="IsPressed" SourceName="PART_ToggleEye" Value="true">
     80                                 <Setter TargetName="PART_ToggleEye" Property="Background">
     81                                     <Setter.Value>
     82                                         <ImageBrush ImageSource="eye.png"/>
     83                                     </Setter.Value>
     84                                 </Setter>
     85                                 <Setter TargetName="PART_ContentHost" Property="Visibility" Value="Collapsed"/>
     86                                 <Setter TargetName="PART_PasswordShower" Property="Visibility" Value="Visible"/>
     87                             </Trigger>
     88                             <!--密码框为空不且没有获取焦点时,设置提示文字显示-->
     89                             <MultiTrigger>
     90                                 <MultiTrigger.Conditions>
     91                                     <Condition Property="local:PasswordBoxHelper.Password"  Value=""/>
     92                                     <Condition Property="IsFocused" Value="False"/>
     93                                 </MultiTrigger.Conditions>
     94                                 <Setter TargetName="PART_PlaceHolder" Property="Visibility" Value="Visible"/>
     95                             </MultiTrigger>
     96                         </ControlTemplate.Triggers>
     97                     </ControlTemplate>
     98                 </Setter.Value>
     99             </Setter>
    100             <Style.Triggers>
    101                 <MultiTrigger>
    102                     <MultiTrigger.Conditions>
    103                         <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
    104                         <Condition Property="IsSelectionActive" Value="false"/>
    105                     </MultiTrigger.Conditions>
    106                     <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
    107                 </MultiTrigger>
    108             </Style.Triggers>
    109         </Style>
    110     </Window.Resources>
    View Code

    代码中使用了PasswordBoxHelper及ControlAttachProperty的类,PasswordBoxHelper用于获取PasswordwordBox的密码,提供给显示框显示明文密码。ControlAttachProperty用于创建提示文字的依赖属性。(注意:两个类放在MainWindow.xaml同级目录中)

    PasswordBoxHelper代码如下:

     1 public class PasswordBoxHelper
     2     {
     3         public static readonly DependencyProperty PasswordProperty =
     4             DependencyProperty.RegisterAttached("Password",
     5             typeof(string), typeof(PasswordBoxHelper),
     6             new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
     7         public static readonly DependencyProperty AttachProperty =
     8             DependencyProperty.RegisterAttached("Attach",
     9             typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, Attach));
    10         private static readonly DependencyProperty IsUpdatingProperty =
    11            DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
    12            typeof(PasswordBoxHelper));
    13 
    14         public static void SetAttach(DependencyObject dp, bool value)
    15         {
    16             dp.SetValue(AttachProperty, value);
    17         }
    18         public static bool GetAttach(DependencyObject dp)
    19         {
    20             return (bool)dp.GetValue(AttachProperty);
    21         }
    22         public static string GetPassword(DependencyObject dp)
    23         {
    24             return (string)dp.GetValue(PasswordProperty);
    25         }
    26         public static void SetPassword(DependencyObject dp, string value)
    27         {
    28             dp.SetValue(PasswordProperty, value);
    29         }
    30         private static bool GetIsUpdating(DependencyObject dp)
    31         {
    32             return (bool)dp.GetValue(IsUpdatingProperty);
    33         }
    34         private static void SetIsUpdating(DependencyObject dp, bool value)
    35         {
    36             dp.SetValue(IsUpdatingProperty, value);
    37         }
    38         private static void OnPasswordPropertyChanged(DependencyObject sender,
    39             DependencyPropertyChangedEventArgs e)
    40         {
    41             PasswordBox passwordBox = sender as PasswordBox;
    42             passwordBox.PasswordChanged -= PasswordChanged;
    43             if (!(bool)GetIsUpdating(passwordBox))
    44             {
    45                 passwordBox.Password = (string)e.NewValue;
    46             }
    47             passwordBox.PasswordChanged += PasswordChanged;
    48         }
    49         private static void Attach(DependencyObject sender,
    50             DependencyPropertyChangedEventArgs e)
    51         {
    52             PasswordBox passwordBox = sender as PasswordBox;
    53             if (passwordBox == null)
    54                 return;
    55             if ((bool)e.OldValue)
    56             {
    57                 passwordBox.PasswordChanged -= PasswordChanged;
    58             }
    59             if ((bool)e.NewValue)
    60             {
    61                 passwordBox.PasswordChanged += PasswordChanged;
    62             }
    63         }
    64         private static void PasswordChanged(object sender, RoutedEventArgs e)
    65         {
    66             PasswordBox passwordBox = sender as PasswordBox;
    67             SetIsUpdating(passwordBox, true);
    68             SetPassword(passwordBox, passwordBox.Password);
    69             SetIsUpdating(passwordBox, false);
    70         }
    71     }
    View Code

    ControlAttachProperty代码如下:

     1 public class ControlAttachProperty
     2     {
     3         public static string GetPlaceHolder(DependencyObject obj)
     4         {
     5             return (string)obj.GetValue(PlaceHolderProperty);
     6         }
     7 
     8         public static void SetPlaceHolder(DependencyObject obj, string value)
     9         {
    10             obj.SetValue(PlaceHolderProperty, value);
    11         }
    12 
    13         // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    14         public static readonly DependencyProperty PlaceHolderProperty =
    15             DependencyProperty.RegisterAttached("PlaceHolder", typeof(string), typeof(ControlAttachProperty), new PropertyMetadata(string.Empty));
    16     }
    View Code

    现在,需要把之前删掉的两句(Style="{StaticResource PasswordBoxStyle1}" 与 local:ControlAttachProperty.PlaceHolder="请输入密码" )加进来。 Style是设置PasswordBox的样式, 在样式里可以重构PasswordBox。local:ControlAttachProperty.PlaceHolder是为passwordbox新增的依赖属性。

    运行代码即可获取实现的效果。

    需要注意的是:

    ①代码中用了两个图片,分别时eye.png与eye_slash.png, 在写Demo的时候,是直接放在MainWindow.xaml同级文件夹里。

    ②xmlns:local="clr-namespace:WpfApp4" , 这里是创建wpf项目的命名空间,喜欢复制代码的兄弟,记得更改为当前创建项目的命名空间。


     作者:Coco①

     出处:https://www.cnblogs.com/ykblog

     声明:本文发表于博客园。如需转载,请注明出处,并在文章页面明显位置给出原文链接,否则保留追究其法律责任的权利。

  • 相关阅读:
    Webpack教程二
    Webpack教程一
    整个互联网行业都缺前端工程师?
    Sublime Text 3 搭建 React.js 开发环境
    Javascript的9张思维导图学习
    实现字体外部有描边
    CSS样式重置
    vue使用过滤器 filters:{}
    修改select的默认样式
    onmouseover和onmouseout鼠标移入移出切换图片的几种实现方法
  • 原文地址:https://www.cnblogs.com/ykblog/p/14583192.html
Copyright © 2020-2023  润新知