WPF之TextBox和PasswordBox水印效果

Posted 十年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF之TextBox和PasswordBox水印效果相关的知识,希望对你有一定的参考价值。

在博客园里看到了好多关于文本框和密码框水印效果的文章,今天有空也来实现一把,最终效果图如下:

文本框的话,稍微好一点直接可以绑定它的Text属性,因为他是个依赖属性,我用了二种方式来实现水印效果:触发器和数据绑定的形式;

一、触发器方式:

<!--触发器的形式进行水印效果-->
    <Style x:Key="TxbTrigger" TargetType="TextBox" BasedOn="{StaticResource TxbBase}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <Grid>
                            <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                            <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                        </Trigger>
                        <Trigger Property="IsKeyboardFocused" Value="True">
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                        </Trigger>
                        <Trigger Property="Text" Value="">
                            <Setter Property="Visibility" TargetName="WaterMark" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

二、数据绑定方式

<!--绑定和转换器的形式进行水印效果-->
    <Style x:Key="TxbBing" TargetType="TextBox" BasedOn="{StaticResource TxbBase}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <Grid>
                            <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                            <TextBlock x:Name="WaterMark" Focusable="False" Visibility="{TemplateBinding Text,Converter={StaticResource TextToVisibility}}" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
                        </Trigger>
                        <Trigger Property="IsKeyboardFocused" Value="True">
                            <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

 

密码框的水印效果就稍微麻烦一点了,因为这个Password它不是依赖属性,所以不能像TextBox的Text进行绑定操作;我这边是通过附加属性的形式进行实现;

代码如下:

 /// <summary>
    /// PasswordBox添加水印辅助类
    /// </summary>
    public class PasswordBoxWaterMark : DependencyObject
    {
        public static bool GetIsMonitoring(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsMonitoringProperty);
        }

        public static void SetIsMonitoring(DependencyObject obj, bool value)
        {
            obj.SetValue(IsMonitoringProperty, value);
        }

        public static readonly DependencyProperty IsMonitoringProperty =
            DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxWaterMark), new UIPropertyMetadata(false, OnIsMonitoringChanged));



        public static int GetPasswordLength(DependencyObject obj)
        {
            return (int)obj.GetValue(PasswordLengthProperty);
        }

        public static void SetPasswordLength(DependencyObject obj, int value)
        {
            obj.SetValue(PasswordLengthProperty, value);
        }

        public static readonly DependencyProperty PasswordLengthProperty =
            DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxWaterMark), new UIPropertyMetadata(0));

        private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var pb = d as PasswordBox;
            if (pb == null)
            {
                return;
            }
            if ((bool)e.NewValue)
            {
                pb.PasswordChanged += PasswordChanged;
            }
            else
            {
                pb.PasswordChanged -= PasswordChanged;
            }
        }

        private static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            var pb = sender as PasswordBox;
            if (pb == null)
            {
                return;
            }
            SetPasswordLength(pb, pb.Password.Length);
        }
    }

PasswordBox的样式如下:

<Style TargetType="PasswordBox">
        <Setter Property="Foreground" Value="Red"/>
        <Setter Property="FontSize" Value="20"/>
        <!--光标的颜色-->
        <Setter Property="CaretBrush" Value="Green"/>
        <Setter Property="Core:PasswordBoxWaterMark.IsMonitoring" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type PasswordBox}">
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <Grid>
                            <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                            <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Opacity="0.5"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Core:PasswordBoxWaterMark.PasswordLength" Value="0">
                            <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

源码如下:Demo.Zip

以上是关于WPF之TextBox和PasswordBox水印效果的主要内容,如果未能解决你的问题,请参考以下文章

WPF自定义控件与样式-TextBox & RichTextBox & PasswordBox样式水印Label标签功能扩展

2021-08-09 WPF控件专题 Label,TextBox,PasswordBox,Button控件介绍

在 PasswordBox 中捕获返回键的最佳方法是啥? (WPF/XAML)

WPF学习第二十二章 文本控件

WPF 之 文本框及密码框添加水印效果

wpf passwobox 添加水印