前言
将一个与占位符绑定的TextBlock放入VisualBrush内,在TextBox的Text为空时使用VisualBrush绘制背景,不为空时背景设为Null。
正因为如此,如果文本框设置了背景,使用此方法就会覆盖原有的背景。但一般不会设置TextBox的背景。
方式1 使用附加属性
添加引用
代码语言:javascript复制xmlns:local="clr-namespace:ZView"
使用方式
代码语言:javascript复制<TextBox
Padding="6"
VerticalContentAlignment="Center"
FontSize="18"
Foreground="gray"
local:PlaceholderManager.Placeholder="请输入密钥"
Text=""
VerticalScrollBarVisibility="Disabled" />
添加类PlaceholderManager
代码语言:javascript复制using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace ZView
{
/// <summary>
/// 占位符的管理类
/// </summary>
public class PlaceholderManager
{
#region Fields
/// <summary>
/// 文本框和Visual画刷对应的字典
/// </summary>
private static readonly Dictionary<TextBox, VisualBrush> TxtBrushes = new Dictionary<TextBox, VisualBrush>();
#endregion Fields
#region Attached DependencyProperty
/// <summary>
/// 占位符的附加依赖属性
/// </summary>
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached(
"Placeholder", typeof(string), typeof(PlaceholderManager),
new PropertyMetadata("请在此处输入", OnPlaceholderChanged));
/// <summary>
/// 获取占位符
/// </summary>
/// <param name="obj">占位符所在的对象</param>
/// <returns>占位符</returns>
public static string GetPlaceholder(DependencyObject obj)
{
return (string)obj.GetValue(PlaceholderProperty);
}
/// <summary>
/// 设置占位符
/// </summary>
/// <param name="obj">占位符所在的对象</param>
/// <param name="value">占位符</param>
public static void SetPlaceholder(DependencyObject obj, string value)
{
obj.SetValue(PlaceholderProperty, value);
}
#endregion Attached DependencyProperty
#region Events Handling
/// <summary>
/// 占位符改变的响应
/// </summary>
/// <param name="d">来源</param>
/// <param name="e">改变信息</param>
public static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var txt = d as TextBox;
if ((txt != null) && (!TxtBrushes.ContainsKey(txt)))
{
var placeholderTextBlock = new TextBox();
var binding = new Binding
{
Source = txt,
//绑定到附加属性
Path = new PropertyPath("(0)", PlaceholderProperty)
};
placeholderTextBlock.SetBinding(TextBox.TextProperty, binding);
//placeholderTextBlock.FontStyle = FontStyles.Italic;
placeholderTextBlock.Opacity = 0.8;
placeholderTextBlock.Padding = new Thickness(10, 0, 0, 0);
placeholderTextBlock.BorderThickness = new Thickness(0, 0, 0, 0);
placeholderTextBlock.Foreground = Brushes.Gray;
var placeholderVisualBrush = new VisualBrush
{
AlignmentX = AlignmentX.Left,
Stretch = Stretch.None,
Visual = placeholderTextBlock
};
txt.Background = placeholderVisualBrush;
txt.TextChanged = PlaceholderTextBox_TextChanged;
txt.Unloaded = PlaceholderTextBox_Unloaded;
TxtBrushes.Add(txt, placeholderVisualBrush);
}
}
/// <summary>
/// 文本变化的响应
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void PlaceholderTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
if ((tb != null) && (TxtBrushes.ContainsKey(tb)))
{
var placeholderVisualBrush = TxtBrushes[tb];
tb.Background = string.IsNullOrEmpty(tb.Text) ? placeholderVisualBrush : null;
}
}
/// <summary>
/// 文本框卸载的响应
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void PlaceholderTextBox_Unloaded(object sender, RoutedEventArgs e)
{
var tb = sender as TextBox;
if ((tb != null) && (TxtBrushes.ContainsKey(tb)))
{
TxtBrushes.Remove(tb);
tb.TextChanged -= PlaceholderTextBox_TextChanged;
tb.Unloaded -= PlaceholderTextBox_Unloaded;
}
}
#endregion Events Handling
}
}
方式2 使用自定义组件
使用方式
代码语言:javascript复制<local:PlaceholderTextBox
Padding="6"
VerticalContentAlignment="Center"
FontSize="18"
Foreground="gray"
Placeholder="请输入密钥"
Text=""
TextWrapping="Wrap"
VerticalScrollBarVisibility="Disabled" />
自定义组件
代码语言:javascript复制using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace ZView
{
/// <summary>
/// 带点位符的文本输入控件
/// </summary>
public class PlaceholderTextBox : TextBox
{
#region Fields
/// <summary>
/// 占位符的文本框
/// </summary>
private readonly TextBox _placeholderTextBlock = new TextBox();
/// <summary>
/// 占位符的画刷
/// </summary>
private readonly VisualBrush _placeholderVisualBrush = new VisualBrush();
#endregion Fields
#region Properties
/// <summary>
/// 占位符的依赖属性
/// </summary>
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.Register(
"Placeholder", typeof(string), typeof(PlaceholderTextBox),
new FrameworkPropertyMetadata("请在此输入", FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// 占位符
/// </summary>
public string Placeholder
{
get { return (string)GetValue(PlaceholderProperty); }
set { SetValue(PlaceholderProperty, value); }
}
#endregion Properties
#region Public Methods
public PlaceholderTextBox()
{
var binding = new Binding
{
Source = this,
Path = new PropertyPath("Placeholder")
};
_placeholderTextBlock.SetBinding(TextBox.TextProperty, binding);
//_placeholderTextBlock.FontStyle = FontStyles.Italic;
_placeholderTextBlock.Padding = new Thickness(10, 0, 0, 0);
_placeholderTextBlock.BorderThickness = new Thickness(0, 0, 0, 0);
_placeholderTextBlock.Foreground = Brushes.Gray;
_placeholderVisualBrush.AlignmentX = AlignmentX.Left;
_placeholderVisualBrush.Stretch = Stretch.None;
_placeholderVisualBrush.Visual = _placeholderTextBlock;
Background = _placeholderVisualBrush;
TextChanged = PlaceholderTextBox_TextChanged;
}
#endregion Public Methods
#region Events Handling
/// <summary>
/// 文本变化的响应
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PlaceholderTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Background = string.IsNullOrEmpty(Text) ? _placeholderVisualBrush : null;
}
#endregion Events Handling
}
}