1,效果
2,代码:
WPF的PasswordBox不能像Winform中的PasswordBox那样,通过PasswordBox.PasswordChar=(char)0显示明文。所以这里使用无外观控件构筑掩码明文切换。
无外观控件遵守Themes/Generic.xaml文件配置.
<ResourceDictionary
xmlns="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>