WPF PasswordBox样式(占位符,清除按钮 )

有些部分是从别人那拿过来的。

效果:


Style:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:controls="clr-namespace:ImageButtonTest01.Control"
                    xmlns:local="clr-namespace:ImageButtonTest01.Themes"
                    xmlns:converter="clr-namespace:ImageButtonTest01.Control.Converter">


    <converter:ImageTextBoxMarginLeftConverter x:Key="ITBMLC"/>
    <converter:PlaceholderFontSizeConverter x:Key="PHFSC"/>
    <converter:ClearButtonEnableTester x:Key="CBET"/>

    <SolidColorBrush x:Key="PasswordBox.Static.Foreground" Color="Black"/>
    <SolidColorBrush x:Key="PasswordBox.Static.Background" Color="Transparent"/>
    <SolidColorBrush x:Key="PasswordBox.Static.SelectionBrush" Color="#808F8787"/>

    <SolidColorBrush x:Key="PasswordBox.Static.BorderBrush" Color="#FF909090"/>
    <SolidColorBrush x:Key="PasswordBox.Focused.BorderBrush" Color="#FF007ACC"/>
    <SolidColorBrush x:Key="PasswordBox.MouseOver.BorderBrush" Color="#FF1E1E1E"/>

    <Style TargetType="{x:Type PasswordBox}" x:Key="DefaultPasswordBox">
        <Setter Property="SelectionBrush" Value="{StaticResource PasswordBox.Static.SelectionBrush}"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="FontSize" Value="22"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="PasswordChar" Value="●"/>
        <Setter Property="Background" Value="{StaticResource PasswordBox.Static.Background}"/>
        <Setter Property="Foreground" Value="{StaticResource PasswordBox.Static.Foreground}"/>
        <Setter Property="BorderBrush" Value="{StaticResource PasswordBox.Static.BorderBrush}"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="CaretBrush" Value="{StaticResource PasswordBox.Static.Foreground}"/>
        <Setter Property="controls:PasswordBoxHelper.Attach" Value="True"/>
        <Setter Property="controls:PasswordBoxHelper.Password" Value="{Binding Path=Password,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type PasswordBox}">
                    <Border x:Name="PART_Root" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                            CornerRadius="{TemplateBinding controls:ControlAttachProperty.CornerRadius}"
                            BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                        <Grid x:Name="PART_InnerGrid">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="{Binding Path=(controls:ControlAttachProperty.CornerRadius).TopLeft, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ITBMLC}}"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition  Width="Auto"/>
                                <ColumnDefinition  Width="Auto"/>
                            </Grid.ColumnDefinitions>

                            <!--内容区域-->
                            <ScrollViewer x:Name="PART_ContentHost" Grid.Column="1" Margin="2"
                                          BorderThickness="0" IsTabStop="False"
                                          VerticalAlignment="Stretch" Background="{x:Null}"
                                          VerticalContentAlignment="Center"/>

                            <TextBlock x:Name="PART_PlaceHolder" Grid.Column="1" Foreground="Black"
                                       IsHitTestVisible="False" Margin="3,0,3,0"
                                       HorizontalAlignment="Left" VerticalAlignment="Center"
                                       SnapsToDevicePixels="True"
                                       Visibility="Collapsed" Opacity="0.6"
                                       TextAlignment="Center"
                                       Text="{Binding Path=(controls:ControlAttachProperty.PlaceHolder), RelativeSource={RelativeSource TemplatedParent}}"
                                       FontSize="{Binding FontSize, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource PHFSC}}"/>

                            <!--附加内容区域-->
                            <!--<Border x:Name="PART_AttachContent" Grid.Column="2" Margin="1"
                                    HorizontalAlignment="Center" VerticalAlignment="Center">
                                <ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center"
                                                Template="{TemplateBinding controls:ControlAttachProperty.AttachContent}"/>
                            </Border>-->
                            <controls:ImageButton x:Name="PART_ClearTextButton" IsTabStop="False" Grid.Column="2"
                                          controls:ControlAttachProperty.IsClearButtonEnabled="True"
                                          FontFamily="/ImageButtonTest01;component/Resources/#iconfont"
                                          Content="" FontSize="20" IsEnabled="True"
                                          HorizontalAlignment="Right"
                                          VerticalAlignment="Center"
                                          Command="controls:ControlAttachProperty.ClearTextCommand"
                                          CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type PasswordBox}}}"
                                          Style="{StaticResource ImageButtonTransparent}"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <!--<DataTrigger Binding="{Binding Path=controls:PasswordBoxHelper.Password, RelativeSource={RelativeSource TemplatedParent}}" Value="">
                            <Setter TargetName="PART_PlaceHolder" Property="Visibility" Value="Visible"/>
                        </DataTrigger>-->
                        <Trigger Property="controls:PasswordBoxHelper.Password"  Value="">
                            <Setter TargetName="PART_PlaceHolder" Property="Visibility" Value="Visible"/>
                            <Setter TargetName="PART_ClearTextButton" Property="IsEnabled" Value="False"/>
                        </Trigger>

                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter  Property="BorderBrush" Value="{StaticResource PasswordBox.MouseOver.BorderBrush}"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter  Property="BorderBrush" Value="{StaticResource PasswordBox.Focused.BorderBrush}"/>
                        </Trigger>

                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="PART_Root" Property="Opacity" Value="0.4"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="ClearButtonPasswordBox" TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource DefaultPasswordBox}">
        <Setter Property="controls:ControlAttachProperty.AttachContent">
            <Setter.Value>
                <ControlTemplate>
                    <!--<controls:ImageButton x:Name="PART_ClearTextButton" IsTabStop="False"
                                          controls:ControlAttachProperty.IsClearButtonEnabled="True"
                                          FontFamily="/ImageButtonTest01;component/Resources/#iconfont"
                                          Content="" FontSize="20"
                                          HorizontalAlignment="Right"
                                          VerticalAlignment="Center"
                                          Command="controls:ControlAttachProperty.ClearTextCommand"
                                          CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type PasswordBox}}}"
                                          Style="{StaticResource ImageButtonTransparent}">
                        <controls:ImageButton.IsEnabled>
                            <MultiBinding Converter="{StaticResource CBET}">
                                <Binding Path="controls:PasswordBoxHelper.Password" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type PasswordBox}}"/>
                            </MultiBinding>
                        </controls:ImageButton.IsEnabled>
                    </controls:ImageButton>-->
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

ControlAttachProperty.cs别人的(解决PasswordBox不能被继承 敲打

public static class ControlAttachProperty
{
    static ControlAttachProperty()
    {
        /* ClearTextCommand */
        ClearTextCommand = new RoutedUICommand();
        ClearTextCommandBinding = new CommandBinding(ClearTextCommand);
        ClearTextCommandBinding.Executed += ClearButtonClick;
    }

    public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius),
                                                                                typeof(ControlAttachProperty), new FrameworkPropertyMetadata(new CornerRadius(0,0,0,0)));
    public static CornerRadius GetCornerRadius(DependencyObject d)
    {
        return (CornerRadius)d.GetValue(CornerRadiusProperty);
    }
    public static void SetCornerRadius(DependencyObject d, CornerRadius value)
    {
        d.SetValue(CornerRadiusProperty, value);
    }

    #region PlaceHolderProperty 占位符
    public static readonly DependencyProperty PlaceHolderProperty = DependencyProperty.RegisterAttached("PlaceHolder", typeof(string), 
                                                        typeof(ControlAttachProperty), new FrameworkPropertyMetadata(""));
    public static string GetPlaceHolder(DependencyObject d)
    {
        return (string)d.GetValue(PlaceHolderProperty);
    }
    public static void SetPlaceHolder(DependencyObject obj, string value)
    {
        obj.SetValue(PlaceHolderProperty, value);
    }
    #endregion

    public static readonly DependencyProperty AttachContentProperty = DependencyProperty.RegisterAttached("AttachContent", typeof(ControlTemplate), 
                                                            typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));
    public static ControlTemplate GetAttachContent(DependencyObject d)
    {
        return (ControlTemplate)d.GetValue(AttachContentProperty);
    }
    public static void SetAttachContent(DependencyObject obj, ControlTemplate value)
    {
        obj.SetValue(AttachContentProperty, value);
    }

    #region ClearTextCommand 清除输入框Text事件命令

    /// <summary>
    /// 清除输入框Text事件命令,需要使用IsClearTextButtonBehaviorEnabledChanged绑定命令
    /// </summary>
    public static RoutedUICommand ClearTextCommand { get; private set; }

    /// <summary>
    /// ClearTextCommand绑定事件
    /// </summary>
    private static readonly CommandBinding ClearTextCommandBinding;

    /// <summary>
    /// 清除输入框文本值
    /// </summary>
    private static void ClearButtonClick(object sender, ExecutedRoutedEventArgs e)
    {
        var tbox = e.Parameter as FrameworkElement;

        if (tbox == null)
        {
            return;
        }

        if (tbox is TextBox)
        {
            ((TextBox)tbox).Clear();
        }
        else if (tbox is PasswordBox)
        {
            ((PasswordBox)tbox).Clear();
        }
        else if (tbox is ComboBox)
        {
            var cb = tbox as ComboBox;
            cb.SelectedItem = null;
            cb.Text = string.Empty;
        }
        else if (tbox is DatePicker)
        {
            var dp = tbox as DatePicker;
            dp.SelectedDate = null;
            dp.Text = string.Empty;
        }

        tbox.Focus();
    }

    #endregion

    #region IsClearTextButtonBehaviorEnabledProperty 清除输入框Text值按钮行为开关(设为ture时才会绑定事件)
    /// <summary>
    /// 清除输入框Text值按钮行为开关
    /// </summary>
    public static readonly DependencyProperty IsClearButtonEnabledProperty = DependencyProperty.RegisterAttached("IsClearButtonEnabled", typeof(bool), 
                    typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, IsClearButtonEnabledChanged));

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetIsClearButtonEnabled(DependencyObject d)
    {
        return (bool)d.GetValue(IsClearButtonEnabledProperty);
    }

    public static void SetIsClearButtonEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsClearButtonEnabledProperty, value);
    }

    /// <summary>
    /// 绑定清除Text操作的按钮事件
    /// </summary>
    private static void IsClearButtonEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var button = d as ImageButton;
        if ((null != button) && (e.OldValue != e.NewValue))
        {
            button.CommandBindings.Add(ClearTextCommandBinding);
        }
    }

    #endregion
}

PasswordBoxHelper.cs别人的,主要解决PasswordBox的Password不是依赖属性问题

public static class PasswordBoxHelper
{
    static PasswordBoxHelper()
    {

    }

    public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(bool),
                                                    typeof(PasswordBoxHelper), new PropertyMetadata(false, AttachToPasswordBox));

    public static bool GetAttach(DependencyObject dp)
    {
        return (bool)dp.GetValue(AttachProperty);
    }
    public static void SetAttach(DependencyObject dp, bool value)
    {
        dp.SetValue(AttachProperty, value);
    }

    public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string),
                                                    typeof(PasswordBoxHelper), new FrameworkPropertyMetadata("", OnPasswordPropertyChanged));
    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 readonly DependencyProperty IsUpdatingProperty = DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), typeof(PasswordBoxHelper));
    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)
    {
        PasswordBox passwordBox = sender as PasswordBox;
        passwordBox.PasswordChanged -= PasswordChanged;

        if (!(bool)GetIsUpdating(passwordBox))
        {
            passwordBox.Password = (string)e.NewValue;
        }
        passwordBox.PasswordChanged += PasswordChanged;
    }

    private static void AttachToPasswordBox(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox passwordBox = sender as PasswordBox;
        if (null == passwordBox)
        {
            return;
        }

        if ((bool)e.OldValue)
        {
            passwordBox.PasswordChanged -= PasswordChanged;
        }

        if ((bool)e.NewValue)
        {
            passwordBox.PasswordChanged += PasswordChanged;
        }
    }

    private static void PasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox passwordBox = sender as PasswordBox;

        SetIsUpdating(passwordBox, true);
        SetPassword(passwordBox, passwordBox.Password);
        SetIsUpdating(passwordBox, false);
    }
}

ImageTextBoxMarginLeftConverter.cs

public class ImageTextBoxMarginLeftConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double)
        {
            double v = (double)value;
            if (null != parameter)
            {
                return v * double.Parse(parameter.ToString());
            }
            return v * 2.0 / 5.0;
        }
        return 0;
    }

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

PlaceholderFontSizeConverter.cs

public class PlaceholderFontSizeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double v = (double)value;

        return (v * 3.5) / 5.0;
    }

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


使用:

<StackPanel Grid.Row="3" Orientation="Horizontal">
    <PasswordBox x:Name="usrPassword" Width="150" Height="40"
        Style="{StaticResource ClearButtonPasswordBox}"
                    Margin="3"
                    control:ControlAttachProperty.PlaceHolder="请输入密码"/>
    <PasswordBox x:Name="usrPassword1" Width="150" Height="40"
        Style="{StaticResource ClearButtonPasswordBox}"
                    PasswordChar="*" Margin="3"
                    control:ControlAttachProperty.PlaceHolder="请输入密码"
                    IsEnabled="False"/>
    <PasswordBox x:Name="usrPassword2" Width="150" Height="40"
        Style="{StaticResource ClearButtonPasswordBox}"
                    PasswordChar="*" Margin="3"
                    control:ControlAttachProperty.PlaceHolder="请输入密码"
                    control:ControlAttachProperty.CornerRadius="10"
                    IsEnabled="True"/>
</StackPanel>


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneOnce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值