WPF实现点击眼睛按钮切换PasswordBox密码可见性的方法
密码框显示/隐藏切换功能修复方案
需求:点击密码输入框右侧眼睛按钮时,显示明文密码并切换为闭眼图标;再次点击隐藏密码,切换回睁眼图标。现有代码存在问题,以下是修正方案:
现有代码问题分析
- 切换按钮未绑定点击事件,无法触发状态切换逻辑
- XAML中缺少明文显示用的
TextBox控件,但C#代码中直接引用了该控件 - 图标未根据密码可见状态自动切换资源
- 未处理密码框与明文输入框的文本同步问题
修正后的XAML代码
<Grid Width="419"> <!-- 密码输入框 --> <PasswordBox x:Name="PasswordBox" Width="419" Height="42" Margin="0,5,0,0" materialDesign:HintAssist.Hint=" Пароль" Foreground="#848386" FontSize="14" materialDesign:HintAssist.FontFamily="{StaticResource Vela Sans M}" HorizontalAlignment="Center" Padding="10,0,0,2" Background="Transparent" VerticalAlignment="Center"/> <!-- 明文显示输入框,默认隐藏 --> <TextBox x:Name="PasswordTextBox" Width="419" Height="42" Margin="0,5,0,0" materialDesign:HintAssist.Hint=" Пароль" Foreground="#848386" FontSize="14" materialDesign:HintAssist.FontFamily="{StaticResource Vela Sans M}" HorizontalAlignment="Center" Padding="10,0,0,2" Background="Transparent" VerticalAlignment="Center" Visibility="Collapsed"/> <!-- 状态切换按钮 --> <Button Background="Transparent" Width="30" Height="40" HorizontalAlignment="Right" BorderBrush="Transparent" Padding="0 0 10 0" Margin="0 0 0 0" Click="TogglePasswordVisibility_Click"> <Image Width="18" Height="18" Margin="0 0 -10 0"> <Image.Style> <Style TargetType="Image"> <!-- 默认显示睁眼图标 --> <Setter Property="Source" Value="{StaticResource eye}"/> <!-- 密码可见时切换为闭眼图标 --> <Style.Triggers> <DataTrigger Binding="{Binding IsPasswordVisible}" Value="True"> <Setter Property="Source" Value="{StaticResource eyeClosed}"/> </DataTrigger> </Style.Triggers> </Style> </Image.Style> </Image> </Button> </Grid>
修正后的C#代码
using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; public partial class MainWindow : Window, INotifyPropertyChanged { private bool _isPasswordVisible; public bool IsPasswordVisible { get => _isPasswordVisible; set { if (_isPasswordVisible != value) { _isPasswordVisible = value; OnPropertyChanged(); } } } public MainWindow() { InitializeComponent(); DataContext = this; IsPasswordVisible = false; // 同步密码框与明文输入框的文本内容 PasswordBox.PasswordChanged += (s, e) => { if (!IsPasswordVisible) PasswordTextBox.Text = PasswordBox.Password; }; PasswordTextBox.TextChanged += (s, e) => { if (IsPasswordVisible) PasswordBox.Password = PasswordTextBox.Text; }; } private void TogglePasswordVisibility_Click(object sender, RoutedEventArgs e) { IsPasswordVisible = !IsPasswordVisible; if (IsPasswordVisible) { PasswordTextBox.Text = PasswordBox.Password; PasswordTextBox.Visibility = Visibility.Visible; PasswordBox.Visibility = Visibility.Collapsed; // 切换后自动聚焦明文输入框,保持输入状态 PasswordTextBox.Focus(); PasswordTextBox.CaretIndex = PasswordTextBox.Text.Length; } else { PasswordBox.Password = PasswordTextBox.Text; PasswordTextBox.Visibility = Visibility.Collapsed; PasswordBox.Visibility = Visibility.Visible; // 切换后自动聚焦密码框 PasswordBox.Focus(); PasswordBox.CaretIndex = PasswordBox.Password.Length; } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
关键修改说明
- 添加了明文显示用的
TextBox控件,与PasswordBox布局保持一致 - 给切换按钮绑定点击事件,关联状态切换逻辑
- 使用
DataTrigger自动根据IsPasswordVisible状态切换图标(需确保资源字典中存在eye和eyeClosed两个图标资源) - 添加文本同步逻辑,避免切换状态时丢失输入内容
- 切换后自动聚焦对应输入框,提升用户操作连贯性
内容的提问来源于stack exchange,提问作者RoDeZ
相关产品推荐
相关产品推荐

