wpf 自定义密码文本框,并且可以双向绑定

复制代码
<UserControl x:Class="项目.UcPassword"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:YouMin_MicroplateReader"
             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
             xmlns:keyboard="clr-namespace:Hs.KeyBoard.WPF.Behavior;assembly=Hs.KeyBoard.WPF" >
    <UserControl.Resources>
        <Style TargetType="CheckBox" x:Key="CheckBoxStyle">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center"></Setter>
            <Setter Property="Margin" Value="0 0 5 0"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="CheckBox">
                        <Image Margin="0 0 5 0" Height="30" Width="30" Stretch="Fill" x:Name="Img" 
                               Source="pack://application:,,,/项目名称;component/Images/GrayWhite.png"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="CheckBox" x:Key="LookStyle">
            <Setter Property="HorizontalAlignment" Value="Right"></Setter>
            <Setter Property="VerticalAlignment" Value="Center"></Setter>
            <Setter Property="Margin" Value="0 0 5 0"></Setter>
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="IsChecked" Value="False" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type CheckBox}">
                        <Image Margin="0 0 5 0" Height="50" Width="55" Stretch="Fill" x:Name="Img"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Opacity" Value="0.6"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter TargetName="Img" Property="Source" Value="pack://application:,,,/项目名称;component/Images/Look.png" />
                            </Trigger>
                            <Trigger Property="IsChecked" Value="False">
                                <Setter TargetName="Img" Property="Source" Value="pack://application:,,,/项目名称;component/Images/UnLook.png" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    <Border Background="#F3FAFF" BorderBrush="#FFFFFF" BorderThickness="3" Height="56" Width="500" >
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBox Background="Transparent" BorderThickness="0" VerticalContentAlignment="Center" Padding="5,0,0,0"
                     Visibility="{Binding TbVisibility,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}" 
                     Text="{Binding Password,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                <i:Interaction.Behaviors>
                    <keyboard:KeyboardBehavior />
                </i:Interaction.Behaviors>
            </TextBox>
            <PasswordBox Background="Transparent" BorderThickness="0" local:PasswordBoxHelper.Attach="True" Padding="5,0,0,0" VerticalContentAlignment="Center"
                          Visibility="{Binding PwVisibility,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}" 
                          local:PasswordBoxHelper.Password="{Binding Password,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                         InputMethod.IsInputMethodEnabled="False">
                <i:Interaction.Behaviors>
                    <keyboard:KeyboardBehavior />
                </i:Interaction.Behaviors>
            </PasswordBox>
            <CheckBox Grid.Column="1" Style="{StaticResource CheckBoxStyle}"  Panel.ZIndex="999"
                                       IsChecked="{Binding IsCleared,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}" 
                                       Visibility ="{Binding ClearVisibility,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}"/>
            <CheckBox Grid.Column="2" Style="{StaticResource LookStyle}"  Panel.ZIndex="999"
                                       IsChecked="{Binding IsChecked,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}">
            </CheckBox>
        </Grid>
    </Border>
</UserControl>

PasswordBoxHelper.cs

复制代码
using System;
using System.Windows;
using System.Windows.Controls;

namespace 项目名称
{
    public static class PasswordBoxHelper
    {
        public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PasswordBoxHelper), new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
        public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, Attach));
        private static readonly DependencyProperty IsUpdatingProperty = DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), typeof(PasswordBoxHelper));

        public static void SetAttach(DependencyObject dp, bool value)
        {
            dp.SetValue(AttachProperty, value);
        }
        public static bool GetAttach(DependencyObject dp)
        {
            return (bool)dp.GetValue(AttachProperty);
        }
        public static string GetPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(PasswordProperty);
        }
        public static void SetPassword(DependencyObject dp, string value)
        {
            dp.SetValue(PasswordProperty, value);
        }
        private static bool GetIsUpdating(DependencyObject dp)
        {
            return (bool)dp.GetValue(IsUpdatingProperty);
        }
        private static void SetIsUpdating(DependencyObject dp, bool value)
        {
            dp.SetValue(IsUpdatingProperty, value);
        }
        private static void OnPasswordPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is not PasswordBox passwordBox || passwordBox == null) { return; }
            try
            {
                passwordBox.PasswordChanged -= PasswordChanged;
                if (!(bool)GetIsUpdating(passwordBox))
                {
                    passwordBox.Password = (string)e.NewValue;
                }
                passwordBox.PasswordChanged += PasswordChanged;
            }
            catch (Exception ex)
            {
                LogHelper.GetSingleObj().WriteLog(ex);
            }
        }
        private static void Attach(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is not PasswordBox passwordBox || passwordBox == null) { return; }
            try
            {
                if ((bool)e.OldValue)
                {
                    passwordBox.PasswordChanged -= PasswordChanged;
                }
                if ((bool)e.NewValue)
                {
                    passwordBox.PasswordChanged += PasswordChanged;
                }
            }
            catch (Exception ex)
            {
                LogHelper.GetSingleObj().WriteLog(ex);
            }
        }

        private static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            if (sender is not PasswordBox passwordBox || passwordBox == null) { return; }
            try
            {
                SetIsUpdating(passwordBox, true);
                SetPassword(passwordBox, passwordBox.Password);
                SetIsUpdating(passwordBox, false);
            }
            catch (Exception ex)
            {
                LogHelper.GetSingleObj().WriteLog(ex);
            }
        }
    }
}

调用

cs 复制代码
 xmlns:local="clr-namespace:项目名"           

<local:UcPassword Password="{Binding Password,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1" Panel.ZIndex="1" HorizontalAlignment="Left" Width="500" Height="56" />

ViewModel

cs 复制代码
  /// <summary>
        /// 密码
        /// </summary>
        [ObservableProperty]
        string _Password = string.Empty;
相关推荐
User_芊芊君子5 小时前
【分布式训练】CANN SHMEM跨设备内存通信库:构建高效多机多卡训练的关键组件
分布式·深度学习·神经网络·wpf
就是有点傻1 天前
WPF按钮走马灯效果
wpf
zuozewei1 天前
虚拟电厂聚合商平台安全技术体系深度解读
安全·wpf
极客智造1 天前
WPF 自定义控件:AutoGrid 实现灵活自动布局的网格控件
wpf
极客智造1 天前
WPF Grid 布局高效扩展:GridHelpers 附加属性工具类全解析
wpf
张人玉1 天前
WPF 多语言实现完整笔记(.NET 4.7.2)
笔记·.net·wpf·多语言实现·多语言适配
暖馒1 天前
深度剖析串口通讯(232/485)
开发语言·c#·wpf·智能硬件
我要打打代码2 天前
WPF控件(2)
wpf
c#上位机2 天前
wpf之行为
c#·wpf
kylezhao20192 天前
深入浅出地理解 C# WPF 中的属性
hadoop·c#·wpf