1,效果
2,代码:
WPF的PasswordBox不能像Winform中的PasswordBox那样,通过PasswordBox.PasswordChar=(char)0显示明文。所以这里使用无外观控件构筑掩码明文切换。
无外观控件遵守Themes/Generic.xaml文件配置.
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:StudentInfoManagerWPF"><Style TargetType="{x:Type local:PasswordBoxExt}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type local:PasswordBoxExt}"><Grid><PasswordBox x:Name="Part_Pwd" VerticalContentAlignment="Center" Padding="0,0,30,0" PasswordChar="{TemplateBinding PasswordChar}"></PasswordBox><TextBox x:Name="Part_TxtBox" VerticalContentAlignment="Center" Padding="0,0,30,0" Visibility="Collapsed" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:PasswordBoxExt, AncestorLevel=1}, Path=Password}"></TextBox><ToggleButton x:Name="Part_Toggle" HorizontalAlignment="Right" MaxWidth="30" ><ToggleButton.Template><ControlTemplate TargetType="ToggleButton"><Grid><Image x:Name="Part_ImgShow" Source="/icon/1.png" Visibility="Collapsed"></Image><Image x:Name="Part_ImgHide" Source="/Icon/2.png" Visibility="Visible"></Image></Grid><ControlTemplate.Triggers ><Trigger Property="IsChecked" Value="true"><Setter Property="Visibility" Value="Visible" TargetName="Part_ImgShow"></Setter><Setter Property="Visibility" Value="Collapsed" TargetName="Part_ImgHide"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></ToggleButton.Template></ToggleButton></Grid><ControlTemplate.Triggers><Trigger SourceName="Part_Toggle" Property="IsChecked" Value="true"><Setter TargetName="Part_TxtBox" Property="Visibility" Value="Visible"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>
public class PasswordBoxExt : Control{public static readonly DependencyProperty PasswordProperty;public static readonly DependencyProperty PasswordCharProperty;PasswordBox passwordBox;static PasswordBoxExt(){DefaultStyleKeyProperty.OverrideMetadata(typeof(PasswordBoxExt), new FrameworkPropertyMetadata(typeof(PasswordBoxExt)));PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(PasswordBoxExt),new PropertyMetadata(new PropertyChangedCallback(PasswordPropertyChanged)));PasswordCharProperty = DependencyProperty.Register("PasswordChar", typeof(char), typeof(PasswordBoxExt), new PropertyMetadata('*'));}private static void PasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){//如此每次变化均导致passwordbox被重新覆盖新值,致使光标每次置于字符串首位而不是字符串末尾//if( (d as PasswordBoxExt).passwordBox != null)// {// (d as PasswordBoxExt).passwordBox.Password = e.NewValue.ToString();// }}/// <summary>/// 密码/// </summary>public string Password{get{return (string)GetValue(PasswordProperty);}set{SetValue(PasswordProperty, value);}}/// <summary>/// 掩码字符/// </summary>public char PasswordChar{get{return (char)GetValue(PasswordCharProperty);}set{SetValue(PasswordCharProperty, value);}}public override void OnApplyTemplate(){base.OnApplyTemplate();passwordBox= this.GetTemplateChild("Part_Pwd") as PasswordBox;ToggleButton btn = this.GetTemplateChild("Part_Toggle") as ToggleButton;if (passwordBox != null){passwordBox.PasswordChanged += Pwdbox_PasswordChanged;}if (btn != null){btn.Click += Btn_Click;}}private void Btn_Click(object sender, RoutedEventArgs e){if((sender as ToggleButton).IsChecked == false){passwordBox.Password = Password;}}private void Pwdbox_PasswordChanged(object sender, RoutedEventArgs e){if(sender is PasswordBox){Password = (sender as PasswordBox).Password;}}}
添加自定义控件
<DockPanel Grid.Row="2" Grid.Column="1" VerticalAlignment="Center"><TextBlock Text="密码:" DockPanel.Dock="Left" FontSize="16"></TextBlock><local:PasswordBoxExt x:Name="pwd01" PasswordChar="#" DockPanel.Dock="Right" MinHeight="30" Margin="10,0,0,0"></local:PasswordBoxExt></DockPanel>