使用附加属性 实现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;
            }
        }

    }
相关推荐
波力海苔夹心脆67515 小时前
C# WPF 资源字典详解:ResourceDictionary、MergedDictionaries 与自定义控件案例
开发语言·c#·wpf·入门教程·resource·资源字典
陈仓主教17 小时前
# WPF CheckBox 控件详解与使用—WPF 中的控件(6)--复选框控件(CheckBox)
wpf
光泽雨3 天前
WPF 音视频四大核心方案对比
wpf·音视频
浪扼飞舟3 天前
WPF(数据绑定)
wpf
samble4 天前
从零搭建半导体设备上位机(四):单实例、启动流程与配置文件,App 里那 526 行到底在干什么
wpf·配置文件·单实例
浪扼飞舟5 天前
WPF(控件的继承树、内容控件、布局控件)
wpf
大江东去浪淘尽千古风流人物8 天前
【HexVIO】DSP卸载双目惯性VIO:Hexagon向量化前端与单帧融合调度深度解析
前端·状态模式·slam·dsp·vio·hexagon·移动端加速
avi91118 天前
电影开源Jevdo - 源码介绍(vue版)没有android 和 没有wpf
android·wpf·框架·数据爬虫·meego·电影管理
吃一碗粉只付一碗钱8 天前
12-给SPA友好的401和403响应
c#·状态模式