WPF中水印输入框应该是有很多地方使用,它的实现也比较简单。可以有两种方法,一是对TextBox进行控制,用代码实现。二是针对TextBox写一个样式实现。
效果如图,
继承一个用户控件,上面放一个textbox,
<UserControl x:Class="TestTextBoxWaterMark.SelfWateMarkTextbox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" >
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBox Name="textBox1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</Grid>
</UserControl>
后台,
/// <summary>
/// WateMarkTextbox.xaml 的交互逻辑
/// </summary>
public partial class SelfWateMarkTextbox : UserControl
{
private const string defaultText = "请输入内容";
public SelfWateMarkTextbox()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(WateMarkTextbox_Loaded);
this.GotFocus += new RoutedEventHandler(WateMarkTextbox_GotFocus);
this.LostFocus += new RoutedEventHandler(WateMarkTextbox_LostFocus);
this.textBox1.TextChanged += new TextChangedEventHandler(TextBox1_TextChanged);
}
void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(this.textBox1.Text) || this.textBox1.IsFocused)
{
this.textBox1.Text = this.textBox1.Text;
}
else
{
this.textBox1.Text = Watermark;
}
}
void WateMarkTextbox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.textBox1.Text))
{
this.textBox1.Text = string.Empty;
}
}
void WateMarkTextbox_GotFocus(object sender, RoutedEventArgs e)
{
if (this.textBox1.Text.Equals(Watermark))
{
this.textBox1.Text = string.Empty;
}
}
void WateMarkTextbox_Loaded(object sender, RoutedEventArgs e)
{
this.textBox1.Text = Watermark;
}
public string Watermark
{
get
{
string result = (string)GetValue(WatermarkProperty);
if (string.IsNullOrEmpty(result))
{
result = defaultText;
}
return result;
}
set { SetValue(WatermarkProperty, value); }
}
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.Register("Watermark", typeof(string), typeof(SelfWateMarkTextbox), new UIPropertyMetadata(defaultText));
}
效果如上图,第一个所示。
第二种,当然为了方便起见,可以直接使用样式控制:
直接继承TextBox,
public class WateMarkTextBox:TextBox
{
private TextBlock wateMarkTextBlock;
private TextBox wateMarkTextBox;
static WateMarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WateMarkTextBox), new FrameworkPropertyMetadata(typeof(WateMarkTextBox)));
}
public WateMarkTextBox()
{
this.GotFocus += new RoutedEventHandler(WateMarkTextBox_GotFocus);
this.LostFocus += new RoutedEventHandler(WateMarkTextBox_LostFocus);
this.TextChanged += new TextChangedEventHandler(WateMarkTextBox_TextChanged);
}
void WateMarkTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (this.wateMarkTextBox!=null && !string.IsNullOrWhiteSpace(this.wateMarkTextBox.Text))
{
this.wateMarkTextBlock.Visibility = Visibility.Hidden;
}
else
{
this.wateMarkTextBlock.Visibility = Visibility.Visible;
}
}
void WateMarkTextBox_GotFocus(object sender, RoutedEventArgs e)
{
this.wateMarkTextBlock.Visibility = Visibility.Hidden;
}
void WateMarkTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (this.wateMarkTextBox != null && !string.IsNullOrWhiteSpace(this.wateMarkTextBox.Text) || !this.IsFocused)
{
this.wateMarkTextBlock.Visibility = Visibility.Hidden;
}
else
{
this.wateMarkTextBlock.Visibility = Visibility.Visible;
}
}
public string WateMark
{
get { return (string)GetValue(WateMarkProperty); }
set { SetValue(WateMarkProperty, value); }
}
public static DependencyProperty WateMarkProperty =
DependencyProperty.Register("WateMark", typeof(string), typeof(WateMarkTextBox), new UIPropertyMetadata("水印"));
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.wateMarkTextBlock = this.GetTemplateChild("ChildWateMark") as TextBlock;
this.wateMarkTextBox = this.GetTemplateChild("ChildTextBox") as TextBox;
}
}
样式,
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:TestTextBoxWaterMark">
<Style TargetType="{x:Type local:WateMarkTextBox}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="#AAB5C0"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="MinWidth" Value="45"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:WateMarkTextBox}">
<Grid Opacity="{TemplateBinding Opacity}" >
<Border BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="5" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1" x:Name="ChildTextBox" VerticalContentAlignment="Center" IsTabStop="True" Margin="2"
Padding="{TemplateBinding Padding}" BorderThickness="0" Background="Transparent" Foreground="{TemplateBinding Foreground}"/>
<TextBlock x:Name="ChildWateMark" VerticalAlignment="Center" Foreground="LightGray" Text="{TemplateBinding WateMark}" Grid.Column="1"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
效果如上图第二个所示。
上面的样式还有更好的实现,参考了网上一个比较好的样式实现,如下
public class PerfectWateMarkTextBox : TextBox
{
private Label wateMarkLable;
private ScrollViewer wateMarkScrollViewer;
static PerfectWateMarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PerfectWateMarkTextBox), new FrameworkPropertyMetadata(typeof(PerfectWateMarkTextBox)));
}
public PerfectWateMarkTextBox()
{
this.Loaded += new RoutedEventHandler(PerfectWateMarkTextBox_Loaded);
}
void PerfectWateMarkTextBox_LostFocus(object sender, RoutedEventArgs e)
{
}
void PerfectWateMarkTextBox_Loaded(object sender, RoutedEventArgs e)
{
this.wateMarkLable.Content = WateMark;
}
void PerfectWateMarkTextBox_GotFocus(object sender, RoutedEventArgs e)
{
this.wateMarkLable.Visibility = Visibility.Hidden;
}
public string WateMark
{
get { return (string)GetValue(WateMarkProperty); }
set { SetValue(WateMarkProperty, value); }
}
public static DependencyProperty WateMarkProperty =
DependencyProperty.Register("WateMark", typeof(string), typeof(PerfectWateMarkTextBox), new UIPropertyMetadata("水印"));
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.wateMarkLable = this.GetTemplateChild("TextPrompt") as Label;
this.wateMarkScrollViewer = this.GetTemplateChild("PART_ContentHost") as ScrollViewer;
}
}
对应的样式,
<Style TargetType="{x:Type local:PerfectWateMarkTextBox}">
<Style.Resources>
<SolidColorBrush x:Key="WatermaskTextBoxWatermaskForeground" Color="#FF707070" />
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="AllowDrop" Value="True"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="BorderBrush" Value="#FF707070"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PerfectWateMarkTextBox}">
<Border x:Name="Border" CornerRadius="2" Padding="2" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" >
<Grid>
<Label x:Name="TextPrompt" Content="{TemplateBinding Tag}" Focusable="False"
Foreground="{DynamicResource WatermaskTextBoxWatermaskForeground}" Height="{TemplateBinding Height}"
Visibility="Collapsed" Padding="5,0,0,0" VerticalContentAlignment="Center" Margin="2,0,0,0"/>
<ScrollViewer Margin="0" x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource TextBoxFocusBorderBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource TextBoxDisabledBackground}"/>
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource TextBoxDisabledBorderBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource TextBoxDisabledForeground}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False"/>
<Condition Property="IsEnabled" Value="True"/>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="TextPrompt" Value="Visible"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsFocused" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Border"
Value="{DynamicResource TextBoxMouseOverBorderBrush}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如上图中,第三个的实现。
详细代码下载:http://download.csdn.net/detail/yysyangyangyangshan/5797465
包括样式实现2的代码下载:http://download.csdn.net/detail/yysyangyangyangshan/5800519