<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 >
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>
<PasswordBox Template="{StaticResource WatermarkedPasswordBoxTemplate}" local:PasswordBoxHelper.Watermark="请输入密码" />
PasswordBox的实现流程较复杂一些 ,大家按如上步骤便可以实现效果