WPF-实现TextBox和PasswordBox显示背景文字

TextBox实现

完成下面的效果
在这里插入图片描述

 <TextBox Name="userId" CaretBrush="White"  Foreground="#ffffff" FontSize="16" BorderBrush="Transparent" BorderThickness="0">
                    <TextBox.Resources>
                        <VisualBrush x:Key="HelpBrush" TileMode="None" Stretch="None" AlignmentX="Left">
                            <VisualBrush.Visual>
                                <Border Background="Black">
                                    <TextBlock  Opacity="0.4" Background="Transparent" FontSize="16"  Foreground="White" Text="请输入用户名"/>
                                </Border>
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </TextBox.Resources>
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Setter Property="Background" Value="Transparent"></Setter>
                            <Style.Triggers>
                                <Trigger Property="Text" Value="{x:Null}">
                                    <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
                                </Trigger>
                                <Trigger Property="Text" Value="">
                                    <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
</TextBox>

TextBox的代码实现很简单,就是通过画刷用TextBlock作背景,将TextBox背景设置为画刷构成的背景。
遇到的问题!!!
在TextBox 的代码中不能直接给Background赋值,如下面的代码。在这里赋值后,通过Style将不能修改背景,因为如下的赋值方法的优秀级较高,Style中将无法修改。建议将正常输入时的背景色设置在Style中,这样就可以避免因为优先级无法呈现效果。上面给出的代码已经将背景这只在Style中

<TextBox Background="Black"></TextBox >

PasswordBox实现

PasswordBoxHelper.cs

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

namespace WpfApplication1
{
    public class PasswordBoxHelper
    {
        static bool isInistialised = false;

        public static string GetWatermark(DependencyObject obj)
        {
            return (string)obj.GetValue(WatermarkProperty);
        }

        public static void SetWatermark(DependencyObject obj, string value)
        {
            obj.SetValue(WatermarkProperty, value);
        }

        public static readonly DependencyProperty WatermarkProperty =
            DependencyProperty.RegisterAttached("Watermark", typeof(string), typeof(PasswordBoxHelper), new UIPropertyMetadata(null, WatermarkChanged));



        public static bool GetShowWatermark(DependencyObject obj)
        {
            return (bool)obj.GetValue(ShowWatermarkProperty);
        }

        public static void SetShowWatermark(DependencyObject obj, bool value)
        {
            obj.SetValue(ShowWatermarkProperty, value);
        }

        public static readonly DependencyProperty ShowWatermarkProperty =
            DependencyProperty.RegisterAttached("ShowWatermark", typeof(bool), typeof(PasswordBoxHelper), new UIPropertyMetadata(false));



        static void WatermarkChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var pwd = obj as PasswordBox;

            CheckShowWatermark(pwd);

            if (!isInistialised)
            {
                pwd.PasswordChanged += new RoutedEventHandler(pwd_PasswordChanged);
                pwd.Unloaded += new RoutedEventHandler(pwd_Unloaded);
                isInistialised = true;
            }
        }

        private static void CheckShowWatermark(PasswordBox pwd)
        {
            pwd.SetValue(PasswordBoxHelper.ShowWatermarkProperty, pwd.Password == string.Empty);
        }

        static void pwd_PasswordChanged(object sender, RoutedEventArgs e)
        {
            var pwd = sender as PasswordBox;
            CheckShowWatermark(pwd);
        }

        static void pwd_Unloaded(object sender, RoutedEventArgs e)
        {
            var pwd = sender as PasswordBox;
            pwd.PasswordChanged -= new RoutedEventHandler(pwd_PasswordChanged);
        }

    }
}

App.xaml

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
             StartupUri="Login.xaml">
    <Application.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <ControlTemplate x:Key="WatermarkedPasswordBoxTemplate" TargetType="{x:Type PasswordBox}">
            <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
                <Grid>
                    <TextBlock Margin="0 4.5 0 0" Background="Transparent" Text="{Binding Path=(local:PasswordBoxHelper.Watermark), RelativeSource={RelativeSource TemplatedParent}}" VerticalAlignment="Center" Foreground="White" Opacity="0.35" FontSize="16"  Visibility="{Binding (local:PasswordBoxHelper.ShowWatermark), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource TemplatedParent}}" />
                    <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Grid>
            </Microsoft_Windows_Themes:ListBoxChrome>
            <ControlTemplate.Triggers>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Application.Resources>
    
</Application>

需要导入的命名空间
在这里插入图片描述
最后一步
xaml中使用

 <PasswordBox Template="{StaticResource   WatermarkedPasswordBoxTemplate}" local:PasswordBoxHelper.Watermark="请输入密码" />

PasswordBox的实现流程较复杂一些 ,大家按如上步骤便可以实现效果

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
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类来实现密码框的水印效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Maybe_ch

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

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

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

打赏作者

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

抵扣说明:

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

余额充值