C# 水印/提示文本/占位符文本框
如何将一些文本放入文本框中,当用户在其中键入内容时,文本框会自动删除?这是一个示例,演示了如何在WPF中创建水印文本框:C# 水印/提示文本/占位符文本框,c#,wpf,textbox,watermark,hint,C#,Wpf,Textbox,Watermark,Hint,如何将一些文本放入文本框中,当用户在其中键入内容时,文本框会自动删除?这是一个示例,演示了如何在WPF中创建水印文本框: <Window x:Class="WaterMarkTextBoxDemo.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:
<Window x:Class="WaterMarkTextBoxDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WaterMarkTextBoxDemo"
Height="200" Width="400">
<Window.Resources>
<SolidColorBrush x:Key="brushWatermarkBackground" Color="White" />
<SolidColorBrush x:Key="brushWatermarkForeground" Color="LightSteelBlue" />
<SolidColorBrush x:Key="brushWatermarkBorder" Color="Indigo" />
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<local:TextInputToVisibilityConverter x:Key="TextInputToVisibilityConverter" />
<Style x:Key="EntryFieldStyle" TargetType="Grid" >
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="20,0" />
</Style>
</Window.Resources>
<Grid Background="LightBlue">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
<TextBlock Margin="5,2" Text="This prompt dissappears as you type..." Foreground="{StaticResource brushWatermarkForeground}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
</Grid>
<Grid Grid.Row="1" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
<TextBlock Margin="5,2" Text="This dissappears as the control gets focus..." Foreground="{StaticResource brushWatermarkForeground}" >
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
<Binding ElementName="txtUserEntry2" Path="Text.IsEmpty" />
<Binding ElementName="txtUserEntry2" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox Name="txtUserEntry2" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
</Grid>
</Grid>
</Window>
注意:这不是我的代码。我找到了,但我认为这是最好的方法。这是一个示例,演示了如何在WPF中创建水印文本框:
<Window x:Class="WaterMarkTextBoxDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WaterMarkTextBoxDemo"
Height="200" Width="400">
<Window.Resources>
<SolidColorBrush x:Key="brushWatermarkBackground" Color="White" />
<SolidColorBrush x:Key="brushWatermarkForeground" Color="LightSteelBlue" />
<SolidColorBrush x:Key="brushWatermarkBorder" Color="Indigo" />
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<local:TextInputToVisibilityConverter x:Key="TextInputToVisibilityConverter" />
<Style x:Key="EntryFieldStyle" TargetType="Grid" >
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="20,0" />
</Style>
</Window.Resources>
<Grid Background="LightBlue">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
<TextBlock Margin="5,2" Text="This prompt dissappears as you type..." Foreground="{StaticResource brushWatermarkForeground}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
</Grid>
<Grid Grid.Row="1" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
<TextBlock Margin="5,2" Text="This dissappears as the control gets focus..." Foreground="{StaticResource brushWatermarkForeground}" >
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
<Binding ElementName="txtUserEntry2" Path="Text.IsEmpty" />
<Binding ElementName="txtUserEntry2" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox Name="txtUserEntry2" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
</Grid>
</Grid>
</Window>
<Window.Resources>
<Style x:Key="TextBoxUserStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxVistaStyle" BasedOn="{x:Null}" TargetType="{x:Type PasswordBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<Grid>
<Label x:Name="lblPwd" Content="Password" FontSize="11" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Verdana" Foreground="#828385" Padding="0"/>
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" TargetName="lblPwd" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<PasswordBox Style="{StaticResource PasswordBoxVistaStyle}" Margin="169,143,22,0" Name="txtPassword" FontSize="14" TabIndex="2" Height="31" VerticalAlignment="Top" />
注意:这不是我的代码。我找到了,但我认为这是最好的方法。
<Window.Resources>
<Style x:Key="TextBoxUserStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PasswordBoxVistaStyle" BasedOn="{x:Null}" TargetType="{x:Type PasswordBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="225"/>
<Setter Property="Height" Value="25"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
<Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
<Grid>
<Label x:Name="lblPwd" Content="Password" FontSize="11" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Verdana" Foreground="#828385" Padding="0"/>
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" TargetName="lblPwd" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<PasswordBox Style="{StaticResource PasswordBoxVistaStyle}" Margin="169,143,22,0" Name="txtPassword" FontSize="14" TabIndex="2" Height="31" VerticalAlignment="Top" />
这有助于检查您的代码。当应用到密码框时,它将显示密码,当用户键入密码时,密码将消失。
这有助于检查您的代码。当应用到密码框时,它将显示密码,当用户键入密码时,密码将消失。您可以创建一个水印,该水印可以添加到任何带有附加属性的
文本框中。以下是附加属性的来源:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
/// <summary>
/// Class that provides the Watermark attached property
/// </summary>
public static class WatermarkService
{
/// <summary>
/// Watermark Attached Dependency Property
/// </summary>
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
"Watermark",
typeof(object),
typeof(WatermarkService),
new FrameworkPropertyMetadata((object)null, new PropertyChangedCallback(OnWatermarkChanged)));
#region Private Fields
/// <summary>
/// Dictionary of ItemsControls
/// </summary>
private static readonly Dictionary<object, ItemsControl> itemsControls = new Dictionary<object, ItemsControl>();
#endregion
/// <summary>
/// Gets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
/// <returns>The value of the Watermark property</returns>
public static object GetWatermark(DependencyObject d)
{
return (object)d.GetValue(WatermarkProperty);
}
/// <summary>
/// Sets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
/// <param name="value">value of the property</param>
public static void SetWatermark(DependencyObject d, object value)
{
d.SetValue(WatermarkProperty, value);
}
/// <summary>
/// Handles changes to the Watermark property.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = (Control)d;
control.Loaded += Control_Loaded;
if (d is ComboBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
}
else if (d is TextBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
((TextBox)control).TextChanged += Control_GotKeyboardFocus;
}
if (d is ItemsControl && !(d is ComboBox))
{
ItemsControl i = (ItemsControl)d;
// for Items property
i.ItemContainerGenerator.ItemsChanged += ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);
// for ItemsSource property
DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i, ItemsSourceChanged);
}
}
#region Event Handlers
/// <summary>
/// Handle the GotFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_GotKeyboardFocus(object sender, RoutedEventArgs e)
{
Control c = (Control)sender;
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
/// <summary>
/// Handle the Loaded and LostFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_Loaded(object sender, RoutedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
}
/// <summary>
/// Event handler for the items source changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>
private static void ItemsSourceChanged(object sender, EventArgs e)
{
ItemsControl c = (ItemsControl)sender;
if (c.ItemsSource != null)
{
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
else
{
ShowWatermark(c);
}
}
/// <summary>
/// Event handler for the items changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>
private static void ItemsChanged(object sender, ItemsChangedEventArgs e)
{
ItemsControl control;
if (itemsControls.TryGetValue(sender, out control))
{
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
}
#endregion
#region Helper Methods
/// <summary>
/// Remove the watermark from the specified element
/// </summary>
/// <param name="control">Element to remove the watermark from</param>
private static void RemoveWatermark(UIElement control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
Adorner[] adorners = layer.GetAdorners(control);
if (adorners == null)
{
return;
}
foreach (Adorner adorner in adorners)
{
if (adorner is WatermarkAdorner)
{
adorner.Visibility = Visibility.Hidden;
layer.Remove(adorner);
}
}
}
}
/// <summary>
/// Show the watermark on the specified control
/// </summary>
/// <param name="control">Control to show the watermark on</param>
private static void ShowWatermark(Control control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
layer.Add(new WatermarkAdorner(control, GetWatermark(control)));
}
}
/// <summary>
/// Indicates whether or not the watermark should be shown on the specified control
/// </summary>
/// <param name="c"><see cref="Control"/> to test</param>
/// <returns>true if the watermark should be shown; false otherwise</returns>
private static bool ShouldShowWatermark(Control c)
{
if (c is ComboBox)
{
return (c as ComboBox).Text == string.Empty;
}
else if (c is TextBoxBase)
{
return (c as TextBox).Text == string.Empty;
}
else if (c is ItemsControl)
{
return (c as ItemsControl).Items.Count == 0;
}
else
{
return false;
}
}
#endregion
}
现在,您可以在任何文本框上添加水印,如下所示:
<AdornerDecorator>
<TextBox x:Name="SearchTextBox">
<controls:WatermarkService.Watermark>
<TextBlock>Type here to search text</TextBlock>
</controls:WatermarkService.Watermark>
</TextBox>
</AdornerDecorator>
您可以创建一个水印,该水印可以添加到任何带有附加属性的文本框中。以下是附加属性的来源:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
/// <summary>
/// Class that provides the Watermark attached property
/// </summary>
public static class WatermarkService
{
/// <summary>
/// Watermark Attached Dependency Property
/// </summary>
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
"Watermark",
typeof(object),
typeof(WatermarkService),
new FrameworkPropertyMetadata((object)null, new PropertyChangedCallback(OnWatermarkChanged)));
#region Private Fields
/// <summary>
/// Dictionary of ItemsControls
/// </summary>
private static readonly Dictionary<object, ItemsControl> itemsControls = new Dictionary<object, ItemsControl>();
#endregion
/// <summary>
/// Gets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
/// <returns>The value of the Watermark property</returns>
public static object GetWatermark(DependencyObject d)
{
return (object)d.GetValue(WatermarkProperty);
}
/// <summary>
/// Sets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
/// <param name="value">value of the property</param>
public static void SetWatermark(DependencyObject d, object value)
{
d.SetValue(WatermarkProperty, value);
}
/// <summary>
/// Handles changes to the Watermark property.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = (Control)d;
control.Loaded += Control_Loaded;
if (d is ComboBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
}
else if (d is TextBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
((TextBox)control).TextChanged += Control_GotKeyboardFocus;
}
if (d is ItemsControl && !(d is ComboBox))
{
ItemsControl i = (ItemsControl)d;
// for Items property
i.ItemContainerGenerator.ItemsChanged += ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);
// for ItemsSource property
DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i, ItemsSourceChanged);
}
}
#region Event Handlers
/// <summary>
/// Handle the GotFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_GotKeyboardFocus(object sender, RoutedEventArgs e)
{
Control c = (Control)sender;
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
/// <summary>
/// Handle the Loaded and LostFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_Loaded(object sender, RoutedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
}
/// <summary>
/// Event handler for the items source changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>
private static void ItemsSourceChanged(object sender, EventArgs e)
{
ItemsControl c = (ItemsControl)sender;
if (c.ItemsSource != null)
{
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
else
{
ShowWatermark(c);
}
}
/// <summary>
/// Event handler for the items changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>
private static void ItemsChanged(object sender, ItemsChangedEventArgs e)
{
ItemsControl control;
if (itemsControls.TryGetValue(sender, out control))
{
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
}
#endregion
#region Helper Methods
/// <summary>
/// Remove the watermark from the specified element
/// </summary>
/// <param name="control">Element to remove the watermark from</param>
private static void RemoveWatermark(UIElement control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
Adorner[] adorners = layer.GetAdorners(control);
if (adorners == null)
{
return;
}
foreach (Adorner adorner in adorners)
{
if (adorner is WatermarkAdorner)
{
adorner.Visibility = Visibility.Hidden;
layer.Remove(adorner);
}
}
}
}
/// <summary>
/// Show the watermark on the specified control
/// </summary>
/// <param name="control">Control to show the watermark on</param>
private static void ShowWatermark(Control control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
layer.Add(new WatermarkAdorner(control, GetWatermark(control)));
}
}
/// <summary>
/// Indicates whether or not the watermark should be shown on the specified control
/// </summary>
/// <param name="c"><see cref="Control"/> to test</param>
/// <returns>true if the watermark should be shown; false otherwise</returns>
private static bool ShouldShowWatermark(Control c)
{
if (c is ComboBox)
{
return (c as ComboBox).Text == string.Empty;
}
else if (c is TextBoxBase)
{
return (c as TextBox).Text == string.Empty;
}
else if (c is ItemsControl)
{
return (c as ItemsControl).Items.Count == 0;
}
else
{
return false;
}
}
#endregion
}
现在,您可以在任何文本框上添加水印,如下所示:
<AdornerDecorator>
<TextBox x:Name="SearchTextBox">
<controls:WatermarkService.Watermark>
<TextBlock>Type here to search text</TextBlock>
</controls:WatermarkService.Watermark>
</TextBox>
</AdornerDecorator>
好吧,这里是我的:不一定是最好的,但因为它很简单,很容易根据您的口味进行编辑
<UserControl x:Class="WPFControls.ShadowedTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFControls"
Name="Root">
<UserControl.Resources>
<local:ShadowConverter x:Key="ShadowConvert"/>
</UserControl.Resources>
<Grid>
<TextBox Name="textBox"
Foreground="{Binding ElementName=Root, Path=Foreground}"
Text="{Binding ElementName=Root, Path=Text, UpdateSourceTrigger=PropertyChanged}"
TextChanged="textBox_TextChanged"
TextWrapping="Wrap"
VerticalContentAlignment="Center"/>
<TextBlock Name="WaterMarkLabel"
IsHitTestVisible="False"
Foreground="{Binding ElementName=Root,Path=Foreground}"
FontWeight="Thin"
Opacity=".345"
FontStyle="Italic"
Text="{Binding ElementName=Root, Path=Watermark}"
VerticalAlignment="Center"
TextWrapping="Wrap"
TextAlignment="Center">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource ShadowConvert}">
<Binding ElementName="textBox" Path="Text"/>
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
</Grid>
最后是隐藏的代码:
using System.Windows;
using System.Windows.Controls;
namespace WPFControls
{
/// <summary>
/// Interaction logic for ShadowedTextBox.xaml
/// </summary>
public partial class ShadowedTextBox : UserControl
{
public event TextChangedEventHandler TextChanged;
public ShadowedTextBox()
{
InitializeComponent();
}
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.Register("Watermark",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextChangedProperty =
DependencyProperty.Register("TextChanged",
typeof (TextChangedEventHandler),
typeof (ShadowedTextBox),
new UIPropertyMetadata(null));
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set
{
SetValue(WatermarkProperty, value);
}
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set{SetValue(TextProperty,value);}
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (TextChanged != null) TextChanged(this, e);
}
public void Clear()
{
textBox.Clear();
}
}
}
使用System.Windows;
使用System.Windows.Controls;
命名空间WPFControls
{
///
///ShadowedTextBox.xaml的交互逻辑
///
公共部分类ShadowedTextBox:UserControl
{
公共事件textchangedventhandler TextChanged;
公共ShadowedTextBox()
{
初始化组件();
}
公共静态只读从属属性WatermarkProperty=
DependencyProperty.Register(“水印”,
类型(字符串),
类型(阴影文本框),
新的UIPropertyMetadata(string.Empty));
公共静态只读DependencyProperty TextProperty=
DependencyProperty.Register(“文本”,
类型(字符串),
类型(阴影文本框),
新的UIPropertyMetadata(string.Empty));
公共静态只读从属属性TextChangedProperty=
DependencyProperty.Register(“TextChanged”,
类型(TextChangedEventHandler),
类型(阴影文本框),
新的UIPropertyMetadata(空);
公共字符串水印
{
获取{return(string)GetValue(WatermarkProperty);}
设置
{
SetValue(水印属性、值);
}
}
公共字符串文本
{
获取{return(string)GetValue(TextProperty);}
set{SetValue(TextProperty,value);}
}
私有void textBox\u TextChanged(对象发送者,textchangedventargs e)
{
如果(TextChanged!=null)TextChanged(this,e);
}
公共空间清除()
{
textBox.Clear();
}
}
}
好吧,这里是我的:不一定是最好的,但因为它很简单,很容易根据您的口味进行编辑
<UserControl x:Class="WPFControls.ShadowedTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFControls"
Name="Root">
<UserControl.Resources>
<local:ShadowConverter x:Key="ShadowConvert"/>
</UserControl.Resources>
<Grid>
<TextBox Name="textBox"
Foreground="{Binding ElementName=Root, Path=Foreground}"
Text="{Binding ElementName=Root, Path=Text, UpdateSourceTrigger=PropertyChanged}"
TextChanged="textBox_TextChanged"
TextWrapping="Wrap"
VerticalContentAlignment="Center"/>
<TextBlock Name="WaterMarkLabel"
IsHitTestVisible="False"
Foreground="{Binding ElementName=Root,Path=Foreground}"
FontWeight="Thin"
Opacity=".345"
FontStyle="Italic"
Text="{Binding ElementName=Root, Path=Watermark}"
VerticalAlignment="Center"
TextWrapping="Wrap"
TextAlignment="Center">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource ShadowConvert}">
<Binding ElementName="textBox" Path="Text"/>
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
</Grid>
最后是隐藏的代码:
using System.Windows;
using System.Windows.Controls;
namespace WPFControls
{
/// <summary>
/// Interaction logic for ShadowedTextBox.xaml
/// </summary>
public partial class ShadowedTextBox : UserControl
{
public event TextChangedEventHandler TextChanged;
public ShadowedTextBox()
{
InitializeComponent();
}
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.Register("Watermark",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text",
typeof (string),
typeof (ShadowedTextBox),
new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty TextChangedProperty =
DependencyProperty.Register("TextChanged",
typeof (TextChangedEventHandler),
typeof (ShadowedTextBox),
new UIPropertyMetadata(null));
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set
{
SetValue(WatermarkProperty, value);
}
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set{SetValue(TextProperty,value);}
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (TextChanged != null) TextChanged(this, e);
}
public void Clear()
{
textBox.Clear();
}
}
}
使用System.Windows;
使用System.Windows.Controls;
命名空间WPFControls
{
///
///ShadowedTextBox.xaml的交互逻辑
///
公共部分类ShadowedTextBox:UserControl
{
公共事件textchangedventhandler TextChanged;
公共ShadowedTextBox()
{
初始化组件();
}
公共静态只读从属属性WatermarkProperty=
DependencyProperty.Register(“水印”,
类型(字符串),
类型(阴影文本框),
新的UIPropertyMetadata(string.Empty));
公共静态只读DependencyProperty TextProperty=
DependencyProperty.Register(“文本”,
类型(字符串),
类型(阴影文本框),
新的UIPropertyMetadata(string.Empty));
公共静态只读从属属性TextChangedProperty=
DependencyProperty.Register(“TextChanged”,
类型(TextChangedEventHandler),
类型(阴影文本框),
新的UIPropertyMetadata(空);
公共字符串水印
{
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
public class TextBoxWatermarked : TextBox
{
public string Watermark
{
get { return (string)GetValue(WaterMarkProperty); }
set { SetValue(WaterMarkProperty, value); }
}
public static readonly DependencyProperty WaterMarkProperty =
DependencyProperty.Register("Watermark", typeof(string), typeof(TextBoxWatermarked), new PropertyMetadata(new PropertyChangedCallback(OnWatermarkChanged)));
private bool _isWatermarked = false;
private Binding _textBinding = null;
public TextBoxWatermarked()
{
Loaded += (s, ea) => ShowWatermark();
}
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
HideWatermark();
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
ShowWatermark();
}
private static void OnWatermarkChanged(DependencyObject sender, DependencyPropertyChangedEventArgs ea)
{
var tbw = sender as TextBoxWatermarked;
if (tbw == null || !tbw.IsLoaded) return; //needed to check IsLoaded so that we didn't dive into the ShowWatermark() routine before initial Bindings had been made
tbw.ShowWatermark();
}
private void ShowWatermark()
{
if (String.IsNullOrEmpty(Text) && !String.IsNullOrEmpty(Watermark))
{
_isWatermarked = true;
//save the existing binding so it can be restored
_textBinding = BindingOperations.GetBinding(this, TextProperty);
//blank out the existing binding so we can throw in our Watermark
BindingOperations.ClearBinding(this, TextProperty);
//set the signature watermark gray
Foreground = new SolidColorBrush(Colors.Gray);
//display our watermark text
Text = Watermark;
}
}
private void HideWatermark()
{
if (_isWatermarked)
{
_isWatermarked = false;
ClearValue(ForegroundProperty);
Text = "";
if (_textBinding != null) SetBinding(TextProperty, _textBinding);
}
}
}
if (d is ComboBox || d is TextBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
if (d is TextBox)
(d as TextBox).TextChanged += Control_TextChanged;
}
private static void Control_TextChanged(object sender, RoutedEventArgs e)
{
var tb = (TextBox)sender;
if (ShouldShowWatermark(tb))
{
ShowWatermark(tb);
}
else
{
RemoveWatermark(tb);
}
}
<DockPanel HorizontalAlignment="Center" VerticalAlignment="Center" Height="80" Width="300" LastChildFill="True">
<Button Margin="5,0,0,0" Click="login_Click" DockPanel.Dock="Right" VerticalAlignment="Center" ToolTip="Login to system">
Login
</Button>
<StackPanel>
<TextBox x:Name="userNameWatermarked" Height="25" Foreground="Gray" Text="UserName" GotFocus="userNameWatermarked_GotFocus"></TextBox>
<TextBox x:Name="userName" Height="25" TextChanged="loginElement_TextChanged" Visibility="Collapsed" LostFocus="userName_LostFocus" ></TextBox>
<TextBox x:Name="passwordWatermarked" Height="25" Foreground="Gray" Text="Password" Margin="0,5,0,5" GotFocus="passwordWatermarked_GotFocus"></TextBox>
<PasswordBox x:Name="password" Height="25" PasswordChanged="password_PasswordChanged" KeyUp="password_KeyUp" LostFocus="password_LostFocus" Margin="0,5,0,5" Visibility="Collapsed"></PasswordBox>
<TextBlock x:Name="loginError" Visibility="Hidden" Foreground="Red" FontSize="12"></TextBlock>
</StackPanel>
</DockPanel>
private void userNameWatermarked_GotFocus(object sender, RoutedEventArgs e)
{
userNameWatermarked.Visibility = System.Windows.Visibility.Collapsed;
userName.Visibility = System.Windows.Visibility.Visible;
userName.Focus();
}
private void userName_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.userName.Text))
{
userName.Visibility = System.Windows.Visibility.Collapsed;
userNameWatermarked.Visibility = System.Windows.Visibility.Visible;
}
}
private void passwordWatermarked_GotFocus(object sender, RoutedEventArgs e)
{
passwordWatermarked.Visibility = System.Windows.Visibility.Collapsed;
password.Visibility = System.Windows.Visibility.Visible;
password.Focus();
}
private void password_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.password.Password))
{
password.Visibility = System.Windows.Visibility.Collapsed;
passwordWatermarked.Visibility = System.Windows.Visibility.Visible;
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
/// <summary>
/// Class that provides the Watermark attached property
/// </summary>
public static class WatermarkService
{
/// <summary>
/// Watermark Attached Dependency Property
/// </summary>
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
"Watermark",
typeof(object),
typeof(WatermarkService),
new FrameworkPropertyMetadata((object)null, new PropertyChangedCallback(OnWatermarkChanged)));
#region Private Fields
/// <summary>
/// Dictionary of ItemsControls
/// </summary>
private static readonly Dictionary<object, ItemsControl> itemsControls = new Dictionary<object, ItemsControl>();
#endregion
/// <summary>
/// Gets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>
/// <returns>The value of the Watermark property</returns>
public static object GetWatermark(DependencyObject d)
{
return (object)d.GetValue(WatermarkProperty);
}
/// <summary>
/// Sets the Watermark property. This dependency property indicates the watermark for the control.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>
/// <param name="value">value of the property</param>
public static void SetWatermark(DependencyObject d, object value)
{
d.SetValue(WatermarkProperty, value);
}
/// <summary>
/// Handles changes to the Watermark property.
/// </summary>
/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>
/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>
private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Control control = (Control)d;
control.Loaded += Control_Loaded;
if (d is TextBox || d is PasswordBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
}
else if (d is ComboBox)
{
control.GotKeyboardFocus += Control_GotKeyboardFocus;
control.LostKeyboardFocus += Control_Loaded;
(d as ComboBox).SelectionChanged += new SelectionChangedEventHandler(SelectionChanged);
}
else if (d is ItemsControl)
{
ItemsControl i = (ItemsControl)d;
// for Items property
i.ItemContainerGenerator.ItemsChanged += ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);
// for ItemsSource property
DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i, ItemsSourceChanged);
}
}
/// <summary>
/// Event handler for the selection changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>
private static void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
#region Event Handlers
/// <summary>
/// Handle the GotFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_GotKeyboardFocus(object sender, RoutedEventArgs e)
{
Control c = (Control)sender;
if (ShouldShowWatermark(c))
{
RemoveWatermark(c);
}
}
/// <summary>
/// Handle the Loaded and LostFocus event on the control
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>
private static void Control_Loaded(object sender, RoutedEventArgs e)
{
Control control = (Control)sender;
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
}
/// <summary>
/// Event handler for the items source changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>
private static void ItemsSourceChanged(object sender, EventArgs e)
{
ItemsControl c = (ItemsControl)sender;
if (c.ItemsSource != null)
{
if (ShouldShowWatermark(c))
{
ShowWatermark(c);
}
else
{
RemoveWatermark(c);
}
}
else
{
ShowWatermark(c);
}
}
/// <summary>
/// Event handler for the items changed event
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>
private static void ItemsChanged(object sender, ItemsChangedEventArgs e)
{
ItemsControl control;
if (itemsControls.TryGetValue(sender, out control))
{
if (ShouldShowWatermark(control))
{
ShowWatermark(control);
}
else
{
RemoveWatermark(control);
}
}
}
#endregion
#region Helper Methods
/// <summary>
/// Remove the watermark from the specified element
/// </summary>
/// <param name="control">Element to remove the watermark from</param>
private static void RemoveWatermark(UIElement control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
Adorner[] adorners = layer.GetAdorners(control);
if (adorners == null)
{
return;
}
foreach (Adorner adorner in adorners)
{
if (adorner is WatermarkAdorner)
{
adorner.Visibility = Visibility.Hidden;
layer.Remove(adorner);
}
}
}
}
/// <summary>
/// Show the watermark on the specified control
/// </summary>
/// <param name="control">Control to show the watermark on</param>
private static void ShowWatermark(Control control)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
// layer could be null if control is no longer in the visual tree
if (layer != null)
{
layer.Add(new WatermarkAdorner(control, GetWatermark(control)));
}
}
/// <summary>
/// Indicates whether or not the watermark should be shown on the specified control
/// </summary>
/// <param name="c"><see cref="Control"/> to test</param>
/// <returns>true if the watermark should be shown; false otherwise</returns>
private static bool ShouldShowWatermark(Control c)
{
if (c is ComboBox)
{
return (c as ComboBox).SelectedItem == null;
//return (c as ComboBox).Text == string.Empty;
}
else if (c is TextBoxBase)
{
return (c as TextBox).Text == string.Empty;
}
else if (c is PasswordBox)
{
return (c as PasswordBox).Password == string.Empty;
}
else if (c is ItemsControl)
{
return (c as ItemsControl).Items.Count == 0;
}
else
{
return false;
}
}
#endregion
}
<Grid Background="{StaticResource brushWatermarkBackground}">
<TextBlock Margin="5,2" Text="Type something..."
Foreground="{StaticResource brushForeground}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry" Background="Transparent"
BorderBrush="{StaticResource brushBorder}" />
</Grid>
private void txtData1_GetFocus(object sender, RoutedEventArgs e)
{
if (txtData1.Text == "TextBox1abc")
{
txtData1.Text = string.Empty;
}
}
private void txtData1_LostFocus(object sender, RoutedEventArgs e)
{
if (txtData1.Text == string.Empty)
{
txtData1.Text = "TextBox1abc";
}
}
<Grid>
<TextBox Width="250" VerticalAlignment="Center" HorizontalAlignment="Left" x:Name="SearchTermTextBox" Margin="5"/>
<TextBlock IsHitTestVisible="False" Text="Enter Search Term Here" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchTermTextBox}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<Grid>
<Grid.Resources>
<ux:NotEmptyConverter x:Key="NotEmptyConverter" />
<Style TargetType="{x:Type Control}" x:Key="DefaultStyle">
<Setter Property="FontSize" Value="20" />
<Setter Property="Margin" Value="10"/>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
</Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource DefaultStyle}"></Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="Placeholder Text Is Here" Foreground="DarkGray" />
<TextBox Grid.Row="0" Name="TextBoxEdit"
Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource DefaultStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=FirstName.Length, FallbackValue=0, TargetNullValue=0}" Value="0">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=FirstName, FallbackValue=0, TargetNullValue=0, Converter={StaticResource NotEmptyConverter}}" Value="false">
<Setter Property="Background" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
public class NotEmptyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var s = value as string;
return string.IsNullOrEmpty(s);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
private String username = "";
private void usernameTextBox_GotFocus(object sender, RoutedEventArgs e) {
if (String.IsNullOrEmpty(username)) {
usernameTextBox.Text = "";
}
}
private void usernameTextBox_LostFocus(object sender, RoutedEventArgs e) {
username = usernameTextBox.Text;
if (String.IsNullOrEmpty(usernameTextBox.Text)) {
usernameTextBox.Text = "Username";
}
}
<TextBox x:Name="usernameTextBox" Text="Username" GotFocus="usernameTextBox_GotFocus" LostFocus="usernameTextBox_LostFocus" />
namespace UI {
public class PlaceholderTextBox : TextBox {
public String Value { get; set; }
public String PlaceholderText { get; set; }
public Brush PlaceholderBrush { get; set; }
private Brush ValuedBrush { get; set; }
public PlaceholderTextBox() : base() {}
protected override void OnInitialized(EventArgs e) {
base.OnInitialized(e);
ValuedBrush = this.Foreground;
if (String.IsNullOrEmpty(this.Text)) {
this.Text = PlaceholderText;
this.Foreground = PlaceholderBrush;
}
}
protected override void OnGotFocus(System.Windows.RoutedEventArgs e) {
this.Foreground = ValuedBrush;
if (String.IsNullOrEmpty(Value)) {
this.Text = "";
}
base.OnGotFocus(e);
}
protected override void OnLostFocus(System.Windows.RoutedEventArgs e) {
Value = this.Text;
if (String.IsNullOrEmpty(this.Text)) {
this.Text = PlaceholderText;
this.Foreground = PlaceholderBrush;
}
base.OnLostFocus(e);
}
}
}
<Window x:Class="UI.LoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:UI"
Initialized="Window_Initialized">
<Grid>
<m:PlaceholderTextBox x:Name="usernameTextBox" PlaceholderText="Username" PlaceholderBrush="Gray" />
</Grid>
</Window>
static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var textbox = (TextBox)d;
textbox.Loaded += UpdateWatermark;
textbox.TextChanged += UpdateWatermark;
}
static void UpdateWatermark(object sender, RoutedEventArgs e) {
var textbox = (TextBox)sender;
var layer = AdornerLayer.GetAdornerLayer(textbox);
if (layer != null) {
if (textbox.Text == string.Empty) {
layer.Add(new WatermarkAdorner(textbox, GetWatermark(textbox)));
} else {
var adorners = layer.GetAdorners(textbox);
if (adorners == null) {
return;
}
foreach (var adorner in adorners) {
if (adorner is WatermarkAdorner) {
adorner.Visibility = Visibility.Hidden;
layer.Remove(adorner);
}
}
}
}
}
contentPresenter = new ContentPresenter {
Content = new TextBlock {
Text = (string)watermark,
Foreground = Control.Foreground,
Background = Control.Background,
FontFamily = Control.FontFamily,
FontSize = Control.FontSize,
...
},
...
}
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="True"/>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/Images/Scan.PNG" Stretch="Uniform" AlignmentX="Left"/>
</Setter.Value>
</Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox adorners:Watermark.Text="Write something here"
adorners:Watermark.TextStyle="{StaticResource AdornerTextStyle}"
adorners:Watermark.VisibleWhen="EmptyAndNotKeyboardFocused"/>
<TextBox x:Name="OrderTxt" HorizontalAlignment="Left" VerticalAlignment="Top" VerticalContentAlignment="Center" Margin="10,10,0,0" Width="188" Height="32"/>
<Label IsHitTestVisible="False" Content="Order number" DataContext="{Binding ElementName=OrderTxt}" Foreground="DarkGray">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Visibility" Value="Collapsed"/>
<Setter Property="Width" Value="{Binding Width}"/>
<Setter Property="Height" Value="{Binding Height}"/>
<Setter Property="Margin" Value="{Binding Margin}"/>
<Setter Property="VerticalAlignment" Value="{Binding VerticalAlignment}"/>
<Setter Property="HorizontalAlignment" Value="{Binding HorizontalAlignment}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;
using System.Windows.Media;
public class HintBehavior : Behavior<ContentControl>
{
public static readonly DependencyProperty HintProperty = DependencyProperty
.Register("Hint", typeof (string), typeof (HintBehavior)
//, new FrameworkPropertyMetadata(null, OnHintChanged)
);
public string Hint
{
get { return (string) GetValue(HintProperty); }
set { SetValue(HintProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty
.Register("Value", typeof (object), typeof (HintBehavior)
, new FrameworkPropertyMetadata(null, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var visible = e.NewValue == null;
d.SetValue(VisibilityProperty, visible ? Visibility.Visible : Visibility.Collapsed);
}
public object Value
{
get { return GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty VisibilityProperty = DependencyProperty
.Register("Visibility", typeof (Visibility), typeof (HintBehavior)
, new FrameworkPropertyMetadata(Visibility.Visible
//, new PropertyChangedCallback(OnVisibilityChanged)
));
public Visibility Visibility
{
get { return (Visibility) GetValue(VisibilityProperty); }
set { SetValue(VisibilityProperty, value); }
}
public static readonly DependencyProperty ForegroundProperty = DependencyProperty
.Register("Foreground", typeof (Brush), typeof (HintBehavior)
, new FrameworkPropertyMetadata(new SolidColorBrush(Colors.DarkGray)
//, new PropertyChangedCallback(OnForegroundChanged)
));
public Brush Foreground
{
get { return (Brush) GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public static readonly DependencyProperty MarginProperty = DependencyProperty
.Register("Margin", typeof (Thickness), typeof (HintBehavior)
, new FrameworkPropertyMetadata(new Thickness(4, 5, 0, 0)
//, new PropertyChangedCallback(OnMarginChanged)
));
public Thickness Margin
{
get { return (Thickness) GetValue(MarginProperty); }
set { SetValue(MarginProperty, value); }
}
private static ResourceDictionary _hintBehaviorResources;
public static ResourceDictionary HintBehaviorResources
{
get
{
if (_hintBehaviorResources == null)
{
var res = new ResourceDictionary
{
Source = new Uri("/Mayflower.Client.Core;component/Behaviors/HintBehaviorResources.xaml",
UriKind.RelativeOrAbsolute)
};
_hintBehaviorResources = res;
}
return _hintBehaviorResources;
}
}
protected override void OnAttached()
{
base.OnAttached();
var t = (ControlTemplate) HintBehaviorResources["HintBehaviorWrapper"];
AssociatedObject.Template = t;
AssociatedObject.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
AssociatedObject.Loaded -= OnLoaded;
var label = (Label) AssociatedObject.Template.FindName("PART_HintLabel", AssociatedObject);
label.DataContext = this;
//label.Content = "Hello...";
label.SetBinding(UIElement.VisibilityProperty, new Binding("Visibility") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(ContentControl.ContentProperty, new Binding("Hint") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(Control.ForegroundProperty, new Binding("Foreground") {Source = this, Mode = BindingMode.OneWay});
label.SetBinding(FrameworkElement.MarginProperty, new Binding("Margin") {Source = this, Mode = BindingMode.OneWay});
}
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="HintBehaviorWrapper" TargetType="{x:Type ContentControl}">
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" />
<Label x:Name="PART_HintLabel" IsHitTestVisible="False" Padding="0" />
</Grid>
</ControlTemplate>
</ResourceDictionary>
<ContentControl>
<i:Interaction.Behaviors>
<behaviors:HintBehavior Value="{Binding Property, RelativeSource={RelativeSource TemplatedParent}}"
Hint="{Binding Hint, RelativeSource={RelativeSource TemplatedParent}}" />
</i:Interaction.Behaviors>
<TextBox ... />
</ContentControl>
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="MM:SS:HH AM/PM" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ComboBox x:Name="comboBox1" SelectedIndex="0" HorizontalAlignment="Left" Margin="202,43,0,0" VerticalAlignment="Top" Width="149">
<ComboBoxItem Visibility="Collapsed">
<TextBlock Foreground="Gray" FontStyle="Italic">Please select ...</TextBlock>
</ComboBoxItem>
<ComboBoxItem Name="cbiFirst1">First Item</ComboBoxItem>
<ComboBoxItem Name="cbiSecond1">Second Item</ComboBoxItem>
<ComboBoxItem Name="cbiThird1">third Item</ComboBoxItem>
</ComboBox>
<AdornerDecorator>
<TextBox Name="txtSomeText"
Width="200"
HorizontalAlignment="Right">
<Controls:TextBoxHelper.Watermark>I'm a watermark!</Controls:TextBoxHelper.Watermark>
</TextBox>
</AdornerDecorator>
namespace PlaceholderForRichTexxBoxInWPF
{
public MainWindow()
{
InitializeComponent();
Application.Current.MainWindow.WindowState = WindowState.Maximized;// maximize window on load
richTextBox1.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(rtb_GotKeyboardFocus);
richTextBox1.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(rtb_LostKeyboardFocus);
richTextBox1.AppendText("Place Holder");
richTextBox1.Foreground = Brushes.Gray;
}
private void rtb_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (sender is RichTextBox)
{
TextRange textRange = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
if (textRange.Text.Trim().Equals("Place Holder"))
{
((RichTextBox)sender).Foreground = Brushes.Black;
richTextBox1.Document.Blocks.Clear();
}
}
}
private void rtb_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
//Make sure sender is the correct Control.
if (sender is RichTextBox)
{
//If nothing was entered, reset default text.
TextRange textRange = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
if (textRange.Text.Trim().Equals(""))
{
((RichTextBox)sender).Foreground = Brushes.Gray;
((RichTextBox)sender).AppendText("Place Holder");
}
}
}
}
<TextBox Controls:TextBoxHelper.Watermark="Watermark"/>
public MainWindow ( )
{
InitializeComponent ( );
txtInput.Text = "Type something here...";
txtInput.Foreground = Brushes.DimGray;
}
private void txtInput_GotFocus ( object sender, EventArgs e )
{
MessageBox.Show ( "got focus" );
txtInput.Text = "";
txtInput.Foreground = Brushes.Red;
}
<Grid>
<Label Content="Placeholder text" VerticalAlignment="Center" Margin="10">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Expression}" Value="">
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<TextBox HorizontalAlignment="Stretch" Margin="5" Background="Transparent"
Text="{Binding Expression, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Padding="5">
</TextBox>
</Grid>
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Search" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Window.Resources>
<Style x:Key="MyWaterMarkStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border Background="White" BorderBrush="#FF7D8683" BorderThickness="1"/>
<ScrollViewer x:Name="PART_ContentHost" Margin="5,0,0,0" VerticalAlignment="Center" />
<Label Margin="5,0,0,0" x:Name="WaterMarkLabel" Content="{TemplateBinding Tag}" VerticalAlignment="Center"
Visibility="Collapsed" Foreground="Gray" FontFamily="Arial"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="WaterMarkLabel" Value="Visible"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="DimGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<TextBox
Style="{StaticResource MyWaterMarkStyle}"
Tag="Search Category"
Grid.Row="0"
Text="{Binding CategorySearch,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
TextSearch.Text="Search Category"
>