WPF带占位符的TextBox

简介: 原文:WPF带占位符的TextBox简介 效果图如下: 使用的XAML代码如下: 其中第一个是带占位符的文本框,第二个使用附加属性装饰在现有的文本框上。
原文: WPF带占位符的TextBox

简介

效果图如下:

1

使用的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:PlaceholderManager.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 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 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

    }
}
目录
相关文章
|
数据可视化 数据处理 C#
WPF技术之TextBox控件
WPF ProgressBar控件用于显示操作的进度。它提供了一个可视化的进度条,用于表示任务的完成程度
127 0
|
C# 数据安全/隐私保护 Windows
WPF技术之TextBox控件
WPF(Windows Presentation Foundation)的TextBox控件是用于用户输入和编辑文本的常见控件
992 0
WPF中给TextBox/TextBlock设置提示文本
WPF中给TextBox/TextBlock设置提示文本
WPF中给TextBox/TextBlock设置提示文本
WPF 点击 Datagrid 中的TextBox 控件获取其所在行的数据
WPF 点击 Datagrid 中的TextBox 控件获取其所在行的数据
|
C#
WPF TextBox自动滚动到最户一行
原文:WPF TextBox自动滚动到最户一行 textBox经常用来显示程序的运行状态或者消息,如何让他自动滚动呢? 在显示消息代码下加一条自动滚动到底部的语句即可:  TextBox1.ScrollToEnd(); (如果要显示垂直滚动条设置VerticalScrollBarVisibility="Auto",如果不显示设置为Hidden) 我用的程序代码如下:   this.
2122 0
|
C#
wpf 开发 -TextBox背景自定义-Decorator
首先在app.xaml文件的下面添加以下样式
1702 0
|
C#
WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数
原文:WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数 正则:^(0\.\d+|[1-9][0-9]|1)$ TextBox绑定正则验证                                                                ...
1445 0
|
Web App开发 C#
WPF 实现带标题的TextBox
原文:WPF 实现带标题的TextBox 这篇博客将分享在WPF中如何创建一个带Title的TextBox。首先请看一下最终的效果, 实现思路:使用TextBlock+TextBox来实现,TextBlock用来显示Title。
1238 0
|
C# 数据安全/隐私保护
WPF实现TextBox水印效果
原文:WPF实现TextBox水印效果 在日常项目中,一个TextBox需要输入用户名,我们通常的做法是先用一个TextBlock来说明,例如下面的截图: 今天将使用另外一种方式来展示,使用水印的方式。
1723 0
|
C# 容器 数据可视化
WPF自定义TextBox及ScrollViewer
原文:WPF自定义TextBox及ScrollViewer   寒假过完,在家真心什么都做不了,可能年龄大了,再想以前那样能专心坐下来已经不行了。回来第一件事就是改了项目的一个bug,最近又新增了一个新的功能,为程序添加了一个消息栏。
1689 0