简介
效果图如下:
使用的XAML代码如下:
<Window x:Class="PlaceHolderTextBox.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:PlaceHolderTextBox" Title="MainWindow" Width="525" Height="350"> <StackPanel> <local:PlaceholderTextBox Placeholder="查询" /> <TextBox x:Name="TxtTest" local:PlaceholderHelper.Placeholder="搜索" /> </StackPanel> </Window>
其中第一个是带占位符的文本框,第二个使用附加属性装饰在现有的文本框上。
原理
将一个与占位符绑定的TextBlock放入VisualBrush内,在TextBox的Text为空时使用VisualBrush绘制背景,不为空时背景设为Null。
正因为如此,如果文本框设置了背景,使用此方法就会覆盖原有的背景。但一般不会设置TextBox的背景。
带占位符的文本框
代码较简单,如下:
using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; namespace PlaceHolderTextBox { /// <summary> /// 带点位符的文本输入控件 /// </summary> public class PlaceholderTextBox:TextBox { #region Fields /// <summary> /// 占位符的文本框 /// </summary> private readonly TextBlock _placeholderTextBlock = new TextBlock(); /// <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(TextBlock.TextProperty, binding); _placeholderTextBlock.FontStyle = FontStyles.Italic; _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 } }
使用附加属性
代码较简单,如下:
using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; namespace PlaceHolderTextBox { /// <summary> /// 占位符的管理类 /// </summary> public class PlaceholderHelper : TextBox { #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(PlaceholderHelper), 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 TextBlock(); var binding = new Binding { Source = txt, //绑定到附加属性 Path = new PropertyPath("(0)", PlaceholderProperty) }; placeholderTextBlock.SetBinding(TextBlock.TextProperty, binding); placeholderTextBlock.FontStyle = FontStyles.Italic; 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 txt = sender as TextBox; if ((txt != null) && (TxtBrushes.ContainsKey(txt))) { var placeholderVisualBrush = TxtBrushes[txt]; txt.Background = string.IsNullOrEmpty(txt.Text) ? placeholderVisualBrush : null; } } /// <summary> /// 文本框卸载的响应 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void PlaceholderTextBox_Unloaded(object sender, RoutedEventArgs e) { var txt = sender as TextBox; if ((txt != null) && (TxtBrushes.ContainsKey(txt))) { TxtBrushes.Remove(txt); txt.TextChanged -= PlaceholderTextBox_TextChanged; txt.Unloaded -= PlaceholderTextBox_Unloaded; } } #endregion Events Handling } }
时间: 2024-10-13 16:57:29