C# WPF 文本框和密码框实现placehode水印效果

7 篇文章 0 订阅

主要功能皆为参考他人代码,在这里做封装汇总,没想到html上面一个placehode就能实现的功能,在wpf上要几百行代码才能实现……

1.准备两个样式文件

PasswordBoxStyle.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:Core="clr-namespace:WpfApp1.Core">
<Style TargetType="PasswordBox">
    <Setter Property="Foreground" Value="#000000"/>
    <Setter Property="FontSize" Value="16"/>
    <!--光标的颜色-->
    <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" Padding="7" 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>

TextBoxStyle.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:Convert="clr-namespace:WpfApp1.Converters"
                xmlns:Core="clr-namespace:WpfApp1.Core"
                xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore">
<Style x:Key="TxbBase" TargetType="TextBox">
    <Setter Property="Foreground" Value="#000000"/>
    <Setter Property="FontSize" Value="14"/>
    <!--光标的颜色-->
    <Setter Property="CaretBrush" Value="Green"/>
    <!--屏蔽系统右键菜单-->
    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu Visibility="Collapsed"/>
        </Setter.Value>
    </Setter>
    <!--用来禁用掉中文输入法-->
    <!--<Setter Property="input:InputMethod.IsInputMethodEnabled" Value="False"/>-->
</Style>
<Convert:TextToVisibility x:Key="TextToVisibility"/>
<!--触发器的形式进行水印效果-->
<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 Padding="7" 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}}" Padding="7" 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>

注意修改xaml文件的头中的命名空间为自己项目的命名控件

做两个工具类,用于转化水印与正文

TextToVisibility.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;

namespace WpfApp1.Converters
{
    /// <summary>
    /// 文本内容转换水印的可见性
    /// </summary>
    public class TextToVisibility : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            //转换后的结果
            Visibility visible = Visibility.Visible;
            if (value != null)
            {
                string text = value.ToString();
                if (!string.IsNullOrEmpty(text.Trim()))
                {
                    int length = text.Length;
                    if (length > 0)
                    {
                        visible = Visibility.Collapsed;
                    }
                }
            }
            return visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return string.Empty;
        }
    }
}
PasswordBoxWaterMark.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp1.Core
{
    /// <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);
        }
    }
}

同样注意修改命名空间

3.在App.xaml中引用样式文件

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Css/TextBoxStyle.xaml"/>
            <ResourceDictionary Source="/Css/PasswordBoxStyle.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

4.在控件中引入样式

TextBox文本框
<TextBox  Style="{StaticResource TxbTrigger}"  Tag="请输入用户名" />
PasswordBox密码框
<PasswordBox Tag="请输入密码" />

实现功能
demo下载地址(引用)
http://files.cnblogs.com/files/OhMonkey/Demo.zip

引用
https://www.cnblogs.com/OhMonkey/p/6057076.html

WPF中,我们可以使用控件的属性来实现文本框密码水印效果(也称为背景文字提示)。下面是实现效果的一些方法: 方法一:使用控件的Placeholder属性 WPF文本框密码控件都有一个名为Placeholder的属性,该属性可以用来显示文本框密码中的默认提示文本。当用户在文本框密码中输入内容后,该提示文本就会自动隐藏。 例如,以下代码演示了在WPF中如何使用Placeholder属性来实现文本框水印效果: ```xml <TextBox Placeholder="请输入文本"></TextBox> ``` 同样地,我们可以在密码中使用Placeholder属性来实现密码水印效果: ```xml <PasswordBox Placeholder="请输入密码"></PasswordBox> ``` 方法二:使用控件的Adorner WPF中的Adorner是一种用于在控件上添加装饰元素的机制。我们可以使用Adorner来实现文本框密码水印效果。 以下是实现效果的一般步骤: 1.定义一个自定义控件,例如WatermarkTextBox。 2.在WatermarkTextBox中定义一个名为Watermark的依赖属性。该属性表示水印提示文本。 3.重写WatermarkTextBox的OnRender方法,使其在控件上绘制水印提示文本。 4.在WatermarkTextBox的TextChanged事件中判断文本框中是否有内容,如果有则隐藏水印提示文本,否则显示水印提示文本。 以下是WatermarkTextBox的示例代码: ```csharp public class WatermarkTextBox : TextBox { public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register( "Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata(default(string))); public string Watermark { get { return (string)GetValue(WatermarkProperty); } set { SetValue(WatermarkProperty, value); } } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if (string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Watermark)) { var formattedText = new FormattedText( Watermark, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), FontSize, Foreground); drawingContext.DrawText(formattedText, new Point(2, 2)); } } protected override void OnTextChanged(TextChangedEventArgs e) { base.OnTextChanged(e); if (string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Watermark)) { InvalidateVisual(); } } } ``` 使用WatermarkTextBox时,只需要在XAML中设置Watermark属性即可: ```xml <local:WatermarkTextBox Watermark="请输入文本"></local:WatermarkTextBox> ``` 同样地,我们也可以定义一个WatermarkPasswordBox类来实现密码水印效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值