WPF Textbox设置Placeholder

2023-02-10 14:38:19 浏览数 (1)

前言

将一个与占位符绑定的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
    }
}

0 人点赞