使用附加属性 实现wpf中的passwordBox 的明文/密文密码切换

csharp 复制代码
    public static class LoginPasswordBoxHelper
    {
        private static bool _isUpdatingPassword = false;

        public static string GetPassword(DependencyObject obj)
        {
            return (string)obj.GetValue(PasswordProperty);
        }

        public static void SetPassword(DependencyObject obj, string value)
        {
            obj.SetValue(PasswordProperty, value);
        }

        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.RegisterAttached("Password", typeof(string), typeof(LoginPasswordBoxHelper),
                new PropertyMetadata(string.Empty, OnPasswordPropertyChanged));

        public static bool GetIsPasswordBindingEnable(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsPasswordBindingEnableProperty);
        }

        public static void SetIsPasswordBindingEnable(DependencyObject obj, bool value)
        {
            obj.SetValue(IsPasswordBindingEnableProperty, value);
        }

        public static readonly DependencyProperty IsPasswordBindingEnableProperty =
            DependencyProperty.RegisterAttached("IsPasswordBindingEnable", typeof(bool), typeof(LoginPasswordBoxHelper),
                new FrameworkPropertyMetadata(OnIsPasswordBindingEnabledChanged));

        private static void OnIsPasswordBindingEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is PasswordBox passwordBox)
            {
                passwordBox.PasswordChanged -= PasswordBoxPasswordChanged;
                if ((bool)e.NewValue)
                {
                    passwordBox.PasswordChanged += PasswordBoxPasswordChanged;
                    // Initialize PasswordProperty value to PasswordBox's current password
                    SetPassword(passwordBox, passwordBox.Password);
                }
            }
        }

        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is PasswordBox passwordBox)
            {
                passwordBox.PasswordChanged -= PasswordBoxPasswordChanged;
                if (!_isUpdatingPassword && passwordBox.Password != (string)e.NewValue)
                {
                    passwordBox.Password = (string)e.NewValue ?? string.Empty;
                }
                passwordBox.PasswordChanged += PasswordBoxPasswordChanged;
            }
        }

        private static void PasswordBoxPasswordChanged(object sender, RoutedEventArgs e)
        {
            if (sender is PasswordBox passwordBox)
            {
                _isUpdatingPassword = true;
                if (GetPassword(passwordBox) != passwordBox.Password)
                {
                    SetPassword(passwordBox, passwordBox.Password);
                }
                _isUpdatingPassword = false;
            }
        }
    }
csharp 复制代码
    public class BoolToContentConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool  b && b)
            {
                return "显示密码";
            }
            else
            {
                return "隐藏密码";
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return new object();
        }
    }

前端代码

html 复制代码
    <Window.Resources>
        <cvt:BoolToContentConverter x:Key="btcc" />
    </Window.Resources>

        <StackPanel
            Grid.Row="2"
            HorizontalAlignment="Center"
            Orientation="Horizontal">
            <Grid>
                <TextBox
                    x:Name="txtBox2"
                    Width="200"
                    Height="35"
                    Margin="0,50,0,0"
                    VerticalContentAlignment="Center"
                    Text="{Binding Pwd, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Visibility="{Binding TxtVis}" />

                <PasswordBox
                    x:Name="passTxt2"
                    Width="200"
                    Height="35"
                    Margin="0,50,0,0"
                    VerticalContentAlignment="Center"
                    deu:LoginPasswordBoxHelper.IsPasswordBindingEnable="True"
                    deu:LoginPasswordBoxHelper.Password="{Binding Pwd, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Visibility="{Binding PwdVis}" />
            </Grid>

            <ToggleButton
                Height="35"
                Margin="20,50,0,0"
                Command="{Binding TBtnCmdCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsChecked}"
                Content="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsChecked, Converter={StaticResource btcc}}"
                Style="{DynamicResource ToggleButtonSuccess}" />
        </StackPanel>

ViewModel:

csharp 复制代码
    public partial class MainViewModel:ObservableObject
    {
        [ObservableProperty]
        private string pwd = string.Empty;

        [ObservableProperty]
        private Visibility pwdVis = Visibility.Visible;

        [ObservableProperty]
        private Visibility txtVis = Visibility.Hidden;

        [RelayCommand]
        public void TBtnCmd(bool isChecked)
        {
            if (isChecked)
            {
                TxtVis = Visibility.Visible;
                PwdVis = Visibility.Hidden;
            }
            else
            {
                TxtVis = Visibility.Hidden;
                PwdVis = Visibility.Visible;
            }
        }

    }
相关推荐
晴天1615 小时前
ES6+ 核心语法
前端·es6·状态模式
samble1 天前
从零搭建工业控制系统(二十二):线程安全与并发控制
c#·wpf·并发·mvvm·线程安全·工业控制
姜穆澜1 天前
OneID 从 0 到 1 完整生产案例(三)
大数据·wpf
dalong101 天前
WPF:MVVM 示例
大数据·wpf
samble2 天前
从零搭建工业控制系统(二十一):状态管理系统——中心状态对象设计
c#·wpf·mvvm·状态管理·工业控制
mengge.cloud2 天前
存储技术基础小白教程
linux·运维·服务器·wpf·存储
漂着的圆木2 天前
MCP 2026-07-28 长任务改造:别再用 HTTP 超时判断任务失败
分布式·架构·状态模式·ai agent
DreamLife☼3 天前
复杂Agent系统架构设计
系统架构·wpf·agent·组件·设计·构架·说明
SamChan903 天前
PDF翻译服务端到端基准测试:4款主流方案的吞吐量、延迟、内存占用对比
服务器·网络·python·ai·pdf·wpf
bugcome_com3 天前
Avalonia 控件模板实战:从 WPF 迁移自定义 Button 样式的完整指南
wpf