WPF带占位符的TextBox

简介

效果图如下:

使用的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

WPF带占位符的TextBox的相关文章

SpringMVC(七) RequestMapping 路径中带占位符的URL

使用方法:在@RequestMapping("/delete/{id}")中,通过{id}带入pathvariable,然后在方法中,通过@PathVariable("变量名称") Iteger id 的方式引入占位符. 控制器代码: package com.tiekui.springmvc.handlers; import org.springframework.stereotype.Controller; import org.springframework.w

spring源码解析(一)---占位符解析替换

一.结构类图 ①.PropertyResolver : Environment的顶层接口,主要提供属性检索和解析带占位符的文本.bean.xml配置中的所有占位符例如${}都由它解析 ②.ConfigurablePropertyResolver : 该接口定义了如何对组件本身进行配置.如:刚刚提到获取value时可以指定任意类型,这依赖于ConversionService进行类型转换,当前接口就提供了对ConversionService的设置和获取.另外,可以配置属性占位符的格式,包括:占位符前

[email&#160;protected]_PathVariable映射URL绑定的占位符

1.概述 带占位符的URL是spring3.0新增的功能,该功能在SpringMVC向REST目标挺进发展过程中具有里程碑的意义: 通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{xxx}占位符可以通过@PathVariable("xxx")绑定到操作方法的入参中: 2.代码 测试类: package com.yk.springmvc.handlers; import org.springframework.stereotype.Cont

占位符行为 PlaceHolderBehavior 的实现以及使用

这个效果我不太会描述 PlaceHolder直译占位符 也有人把这个效果叫水印效果 就是和HTML5的PlaceHolder属性一样的效果 上图直观: 使用方法: 首先下载 占位符行为dll.rar 在项目中引用dll 1.在VS中 引用System.Windows.Interactivity.dll程序集 在xmal页面添加引用: 然后附加到TextBox 设置行为的属性 Text值肯定是要设置的了,这个是提示的文字.然后按需设置其他属性.不设置的话,默认取被附加的TextBox的值. 2.在

Android字符串中使用占位符

一是可以通过Java的 String.format(String format, Object... args) 方法来实现 二则是通过Android自带的 getResources().getString(int id, Object... formatArgs) 实现 占位符的语法可以参考Java文档 简单演示下第二种方法 strings.xml 1 <string name="boolean_conversion">Boolean: %1$b\n</string

C++基础2 引用 函数扩展: 默认值 占位符 指针 重载 类:引用类指针 声明实现分开写

[难点]指针引用 [email protected]:~/c++$ cat main.cpp  #include <stdlib.h> #include "iostream" using namespace std; int a = 20; struct Teacher { int age; char name[64]; }; int fun1(struct Teacher ** p) { int ret = 0; if(p == NULL) { ret = -1; ret

Sass 混合宏、继承、占位符 详解

混合宏-声明混合宏如果你的整个网站中有几处小样式类似,比如颜色,字体等,在 Sass 可以使用变量来统一处理,那么这种选择还是不错的.但当你的样式变得越来越复杂,需要重复使用大段的样式时,使用变量就无法达到我们目了.这个时候 Sass 中的混合宏就会变得非常有意义.1.声明混合宏不带参数混合宏:在 Sass 中,使用"@mixin"来声明一个混合宏.如: 1 @mixin border-radius{ 2 -webkit-border-radius: 5px; 3 border-rad

Sass之继承,混合宏,占位符的用法总结

Sass强大的功能,受到web前端开发人员的各种青睐. 混合宏的用法,关键字@mixin,声明带参数的函数,在有需要的地方通过@include调用这一函数值 //SCSS中混合宏使用@mixin mt($var){ margin-top: $var; } .block { @include mt(5px); span { display:block; @include mt(5px); }} .header { color: orange; @include mt(5px); span{ dis

解决Spring国际化文案占位符失效问题的方法

写在前面:接下来很长一段时间的文章主要会记录一些项目中实际遇到的问题及对应的解决方案,在相应代码分析时会直指问题所在,不会将无关的流程代码贴出,感兴趣的读者可以自行跟踪.同时希望大家能够将心得体会在评论区分享出来,让大家共同进步! 环境或版本:Spring 3.2.3 现象:利用Spring自带的MessageSource来处理国际化文案,us状态下的文案有部分占位符未被替换,cn状态下的正常.文案如下: tms.pallet.order.box.qty=The total palletized