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

TextBox实现

完成下面的效果
WPF-实现TextBox和PasswordBox显示背景文字_第1张图片

 <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>

需要导入的命名空间
WPF-实现TextBox和PasswordBox显示背景文字_第2张图片
最后一步
xaml中使用

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

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

你可能感兴趣的:(WPF)