• WPF PasswordBox控件使用


    一、PasswordBox的SecurePassword属性

    正常的String类型值,在脱离开作用域之后,其值在内存中并不会被立即销毁,这时如果有人恶意扫描你的内存,程序中所保存的机密信息就会暴露;于是就有了System.Security.SecureString,SecureString表示一个应保密的文本,它在初始化时就已被加密,并且脱离作用域后会被立即销毁。PasswordBox提供了SecurePassword属性,该属性提供的是一个SecureString类型,SecureString类型转换为string类型如下所示:

     IntPtr p = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(this.LoginPasswordBox.SecurePassword);
     string password = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(p);
    

    二、PasswordBox的密码明文展示样式实现

    由于Password属性不是依赖属性,所以要实现密码的明文展示需要通过附加属性来实现,具体代码如下所示:

    image

     public class PasswordBoxAttached
        {
            public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PasswordBoxAttached), new PropertyMetadata("", PasswordPropertyChangedCallback));
            [AttachedPropertyBrowsableForType(typeof(System.Windows.Controls.PasswordBox))]
            public static string GetPassword(DependencyObject obj)
            {
                return (string)obj.GetValue(PasswordProperty);
            }
            public static void SetPassword(DependencyObject obj, string value)
            {
                obj.SetValue(PasswordProperty, value);
            }
            private static void PasswordPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                if (d is System.Windows.Controls.PasswordBox pb)
                {
                    pb.Password = e.NewValue.ToString();
                    pb.GetType().GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(pb, new object[] { pb.Password.Length, 0 });
                }
            }
        }
    
     <Window.Resources>
            <Style x:Key="ToggleButtonStyle" TargetType="ToggleButton">
                <Setter Property="Margin" Value="5,0"></Setter>
                <Setter Property="Background" Value="Transparent"></Setter>
                <Setter Property="BorderThickness" Value="0"></Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ToggleButton">
                            <Image x:Name="IconImage" Source="Resources/eye_close.png"></Image>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="IconImage" Property="Source" Value="Resources/eye_open.png"></Setter>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="IconImage" Property="Source" Value="Resources/eye_open.png"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="PasswordBox">
                <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
                <Setter Property="Padding" Value="5,0"></Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="PasswordBox">
                            <Border Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    CornerRadius="4">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"></ColumnDefinition>
                                        <ColumnDefinition Width="32"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <ScrollViewer Grid.Column="0" x:Name="PART_ContentHost"></ScrollViewer>
                                    <TextBlock  Grid.Column="0" x:Name="MessageTextBlock"
                                               Text="{TemplateBinding Tag}"
                                               FontSize="{TemplateBinding FontSize}"
                                               Foreground="{TemplateBinding Foreground}"
                                               Padding="{TemplateBinding Padding}"
                                               VerticalAlignment="Center"
                                               Visibility="Hidden"></TextBlock>
                                    <TextBox Grid.Column="0" VerticalContentAlignment="Center"
                                             BorderThickness="0" Visibility="Hidden"
                                             FontSize="{TemplateBinding FontSize}"
                                             Foreground="{TemplateBinding Foreground}"
                                             Margin="{TemplateBinding Padding}"
                                             Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=PasswordBox}, Path=(local:PasswordBoxAttached.Password)}"
                                             x:Name="PasswordTextBox"></TextBox>
                                    <ToggleButton Grid.Column="1" x:Name="CheckedToggleButton" Focusable="False" 
                                                  Style="{StaticResource ToggleButtonStyle}"></ToggleButton>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsKeyboardFocused" Value="False"></Condition>
                                        <Condition Property="local:PasswordBoxAttached.Password" Value=""></Condition>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="MessageTextBlock" Property="Visibility" Value="Visible"></Setter>
                                    <Setter TargetName="MessageTextBlock" Property="Opacity" Value="0.5"></Setter>
                                </MultiTrigger>
                                <DataTrigger Binding="{Binding ElementName=CheckedToggleButton, Path=IsChecked}" Value="True">
                                    <Setter TargetName="PasswordTextBox" Property="Visibility" Value="Visible"></Setter>
                                    <Setter TargetName="PART_ContentHost" Property="Visibility" Value="Hidden"></Setter>
                                </DataTrigger>
                            </ControlTemplate.Triggers> 
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
        <StackPanel Margin="20">
            <PasswordBox Height="60" 
                         Tag="请输入密码"
                         x:Name="LoginPasswordBox"
                         PasswordChanged="LoginPasswordBox_OnPasswordChanged"></PasswordBox>
        </StackPanel>
    
      private void LoginPasswordBox_OnPasswordChanged(object sender, RoutedEventArgs e)
      {
          if (sender is System.Windows.Controls.PasswordBox pb)
          {
               PasswordBoxAttached.SetPassword(pb, pb.Password);
          }
      }
    
  • 相关阅读:
    idea 将java导出为可执行jar及导入jar依赖
    使用idea 调试java -jar xxx.jar方式启动
    springboot 打成的jar包在ClassLoader().getResource方法读取文件为null
    maven 使用dependencyManagement统一管理依赖版本
    Win10系列:C#应用控件基础5
    Win10系列:C#应用控件基础4
    Win10系列:C#应用控件基础3
    Win10系列:C#应用控件基础2
    Win10系列:C#应用控件基础1
    Win10系列:UWP界面布局进阶9
  • 原文地址:https://www.cnblogs.com/dongweian/p/16414666.html
Copyright © 2020-2023  润新知