如何为C# WinForms的TextBox控件添加占位符(含密码框场景)
为C# WinForms控件添加占位符的实现方案
刚好做过类似的需求,给你分享一套完整的实现思路和代码,完美匹配你提到的两个核心要求:空文本失焦时显示占位符、密码框模式下占位符明文显示,输入时切换为密码字符。
核心实现思路
WinForms原生TextBox没有内置占位符功能,直接修改Text属性模拟的话,在密码框模式(UsePasswordChar=true)下会导致占位符被掩码成密码字符,不符合需求。所以正确的思路是:
- 不修改控件的
Text属性,而是通过重绘控件的方式绘制占位符文本 - 利用
GotFocus/LostFocus事件判断何时显示/隐藏占位符 - 结合
TextChanged事件,确保用户输入内容时自动隐藏占位符
具体代码实现(自定义TextBox控件)
最方便的方式是封装一个自定义TextBox控件,这样可以在整个项目中复用,无需重复写事件逻辑:
using System.Drawing; using System.Windows.Forms; public class PlaceholderTextBox : TextBox { // 存储占位符文本 private string _placeholderText = "请输入内容"; // 标记是否需要显示占位符 private bool _showPlaceholder; // 对外暴露占位符设置属性 public string PlaceholderText { get => _placeholderText; set { _placeholderText = value; // 更改后触发重绘 Invalidate(); } } public PlaceholderTextBox() { // 绑定必要的事件 GotFocus += PlaceholderTextBox_GotFocus; LostFocus += PlaceholderTextBox_LostFocus; Paint += PlaceholderTextBox_Paint; TextChanged += PlaceholderTextBox_TextChanged; } private void PlaceholderTextBox_TextChanged(object sender, System.EventArgs e) { // 用户输入内容时,自动隐藏占位符 if (!string.IsNullOrEmpty(Text)) { _showPlaceholder = false; Invalidate(); } } private void PlaceholderTextBox_GotFocus(object sender, System.EventArgs e) { // 获得焦点时,如果当前显示占位符,就隐藏它 if (_showPlaceholder) { _showPlaceholder = false; Invalidate(); } } private void PlaceholderTextBox_LostFocus(object sender, System.EventArgs e) { // 失去焦点且文本为空时,显示占位符 if (string.IsNullOrEmpty(Text)) { _showPlaceholder = true; Invalidate(); } } private void PlaceholderTextBox_Paint(object sender, PaintEventArgs e) { // 满足条件时绘制占位符 if (_showPlaceholder && string.IsNullOrEmpty(Text)) { // 使用灰色文本模拟占位符样式,可自定义颜色 using (var placeholderBrush = new SolidBrush(SystemColors.GrayText)) { // 模拟原生文本的padding和对齐方式,视觉更统一 var textRect = new Rectangle( Padding.Left, Padding.Top, ClientSize.Width - Padding.Left - Padding.Right, ClientSize.Height - Padding.Top - Padding.Bottom ); // 匹配控件的文本对齐设置 var textFormat = new StringFormat(); switch (TextAlign) { case HorizontalAlignment.Left: textFormat.Alignment = StringAlignment.Near; break; case HorizontalAlignment.Center: textFormat.Alignment = StringAlignment.Center; break; case HorizontalAlignment.Right: textFormat.Alignment = StringAlignment.Far; break; } // 绘制占位符文本 e.Graphics.DrawString(_placeholderText, Font, placeholderBrush, textRect, textFormat); } } } // 重写WndProc处理密码框模式下的重绘消息 protected override void WndProc(ref Message m) { base.WndProc(ref m); // WM_PAINT消息,确保密码框切换时占位符正常显示 if (m.Msg == 0x000F) { if (_showPlaceholder && string.IsNullOrEmpty(Text)) { Invalidate(); } } } }
使用方法
设计器方式
编译项目后,这个自定义控件会出现在WinForms设计器的工具箱里,直接拖到窗体上即可,然后在属性面板设置:
PlaceholderText:自定义占位符内容UsePasswordChar:设置为true即可开启密码框模式
代码创建方式
// 创建密码框实例 var passwordInput = new PlaceholderTextBox(); passwordInput.PlaceholderText = "请输入登录密码"; passwordInput.UsePasswordChar = true; passwordInput.Location = new Point(20, 20); passwordInput.Size = new Size(250, 28); this.Controls.Add(passwordInput); // 创建普通输入框实例 var usernameInput = new PlaceholderTextBox(); usernameInput.PlaceholderText = "请输入用户名"; usernameInput.Location = new Point(20, 60); usernameInput.Size = new Size(250, 28); this.Controls.Add(usernameInput);
关键细节说明
- 密码框兼容性:因为占位符是通过Paint事件绘制的,没有修改TextBox的
Text属性,所以即使UsePasswordChar=true,占位符依然是明文显示,用户输入时直接显示密码字符,完全符合需求。 - 视觉一致性:绘制占位符时考虑了控件的
Padding和TextAlign属性,和原生文本的显示位置完全一致,不会出现偏移。 - 复用性:自定义控件的方式可以在整个项目中重复使用,无需为每个TextBox绑定事件。
内容的提问来源于stack exchange,提问作者Hassan Kotti




