简介

效果图如下:

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

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

  1. 在Java中编写带占位符的SQL语句

    C#中SQL中带占位符的语句 假设有一张学员信息表Student,通过表中的ID来找学员,查询的SQL语句如下 string sql = string.Format("select * fr ...

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

    使用方法:在@RequestMapping("/delete/{id}")中,通过{id}带入pathvariable,然后在方法中,通过@PathVariable("变 ...

  3. Swift3 重写一个带占位符的textView

    class PlaceStrTextView: UIView,UITextViewDelegate{ var palceStr = "即将输入的信息" //站位文字 var inp ...

  4. 用mysql写带占位符的select语句

    sql.append(" AND t.f_user_name LIKE CONCAT('%',?,'%')");//模糊查询 sql.append(" AND t.f_u ...

  5. 【SpringMVC】SpringMVC系列3之@PathVariable映射URL占位符参数

    3.@PathVariable映射URL占位符参数 3.1.概述 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义. ...

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

    一.结构类图 ①.PropertyResolver : Environment的顶层接口,主要提供属性检索和解析带占位符的文本.bean.xml配置中的所有占位符例如${}都由它解析 ②.Config ...

  7. SpringMVC(三):@RequestMapping中的URL中设定通配符,可以使用@PathVariable映射URL绑定的占位符

    1)带占位符的URL是Spring3.0新增的功能,该功能在SpringMVC向REST目标挺进发展过程中具有里程碑的意义. 2)通过@PathVariable可以将URL中占位符参数绑定到控制器处理 ...

  8. 004 @PathVariable映射URL绑定的占位符

    一: 1.介绍 带占位符的URL是spring 3.0新增的功能,是向REST发展的重要阶段. @PathVariable可以将URL中占位符参数绑定到控制器处理的方法的入参中:URL中的{xxx}占 ...

  9. SpringBoot环境属性占位符解析和类型转换

    前提 前面写过一篇关于Environment属性加载的源码分析和扩展,里面提到属性的占位符解析和类型转换是相对复杂的,这篇文章就是要分析和解读这两个复杂的问题.关于这两个问题,选用一个比较复杂的参数处 ...

随机推荐

  1. JAVA中-面向网络编程---单层交互

    面向网络编程---单层交互: 客户端说明: /* * 实现TCP客户端,链接到服务器 * 和服务器实现数据交互 * 实现TCP客户端的类 java.net.Scoket * 构造方法: * Socke ...

  2. String类的操作方法

    因String属于java核心包lang包的东西,所以不需要导包! /* * 字符串操作 * */ String name = "jck"; String name1 = &quo ...

  3. ZooKeeper学习1---简单介绍

    一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术主要用来解决分布式环境当中多个进程之间的同 ...

  4. [CISCO] 交换机间链路聚合端口聚合

    [CISCO] 交换机间链路聚合端口聚合 一.Introduction 端口通道( port channel ) 是一种聚合多个物理接口 ( that ) 创建一个逻辑接口.你可以捆扎( bundle ...

  5. mxonline实战2, 后台管理神器xadmin

          对应github地址:xadmin的使用   第三天:xadmin的安装以及各应用模型的后台管理注册     一. 安装xamdin     1. 源码包下载地址 https://gith ...

  6. 关于字典的几个类--defaultdict,OrderedDict, zip()

    一.  1个键对应多个值 比如:d = {'a' : [1, 2, 3],  'b' : [4, 5]},可以使用 collections 模块中的 defaultdict 来构造这样的字典 from ...

  7. docker微服务部署之:一,搭建Eureka微服务项目

    先说明一下docker需要搭建的微服务的基本情况: 项目情况:一个demo_parent项目,下面三个子模块:demo_eureka(eureka服务).demo_article(文章服务).demo ...

  8. 常见 CentOS 7 安装问题

    问题一: 解决办法:网上安装文章推荐的的刻录工具多是 ultraiso,有时候可能会出现错误,这时候最简单的解决办法是换由RedHat推荐的刻录工具,fedora media writer,不过这个工 ...

  9. 算法图解学习笔记01:二分查找&大O表示法

    二分查找 二分查找又称折半查找,其输入的必须是有序的元素列表.二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止:如果x<a[ ...

  10. C#静态和实例

    静态 实例 关键字static修饰类或方法 不能使用static修饰类或方法 修饰后类直接调用 需要先实例化对象,用对象调用 静态只会执行调用一次,并且在程序退出之前会一直保持状态,占领内存 实例化一 ...