【问题标题】:How do I implement a TextBox that displays "Type here"?如何实现显示“在此处输入”的文本框?
【发布时间】:2010-03-21 12:50:43
【问题描述】:

在用户将文本输入TextBox 之前显示“Type here to ...”是当今众所周知的可用性功能。如何在 C# 中实现这一功能?

我的想法是覆盖OnTextChanged,但是处理文本从“在此处输入”的变化的逻辑有点棘手......

在初始化时显示“在此处输入”并在第一次输入时将其删除很容易,但我想在每次输入的文本变为空时显示消息。

【问题讨论】:

  • 这是 ASP.NET 还是 windows 窗体?
  • 您对什么技术感兴趣?是 ASP.NET、winforms 还是 WPF,或者是 silverlight?无论如何,它被称为“水印文本框”,您可以在每种技术上找到很多。
  • stackoverflow.com/questions/4902565/… 为未来看起来更好和更新答案的用户。

标签: c# winforms textbox


【解决方案1】:

对我有用的东西:

this.waterMarkActive = true;
this.textBox.ForeColor = Color.Gray;
this.textBox.Text = "Type here";

this.textBox.GotFocus += (source, e) =>
  {
    if (this.waterMarkActive)
    {
      this.waterMarkActive = false;
      this.textBox.Text = "";
      this.textBox.ForeColor = Color.Black;
    }
  };

this.textBox.LostFocus += (source, e) =>
  {
    if (!this.waterMarkActive && string.IsNullOrEmpty(this.textBox.Text))
    {
      this.waterMarkActive = true;
      this.textBox.Text = "Type here";
      this.textBox.ForeColor = Color.Gray;
    }
  };

其中bool waterMarkActive 是类成员变量,textBox 是TextBox。不过这可能应该被封装:) 这种方法可能存在一些问题,但我目前不知道有任何问题。

我最近发现 Windows 支持文本框中的水印;它们被称为提示横幅(参见here)。很容易实现:

// Within your class or scoped in a more appropriate location:
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

// In your constructor or somewhere more suitable:
SendMessage(textBox.Handle, 0x1501, 1, "Please type here.");

其中textBox 是TextBox 的一个实例,0x1501 是Windows 消息EM_SETCUEBANNER 的代码,wParam 可以是TRUE(非零)或FALSE(零),lParam 是您要显示的水印。 wParam 指示何时应显示提示横幅;如果设置为TRUE,那么即使控件有焦点也会显示提示横幅。

【讨论】:

  • 如果您使用多行文本框,提示横幅将不起作用。
  • 这就像单行 TextBox 控件的魅力。谢谢!
【解决方案2】:

您正在寻找的是带有“水印”的文本框。

有一个 C# here 的示例实现,全部归功于 Wael Alghool。

他的代码的相关部分是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace wmgCMS
{
    class WaterMarkTextBox : TextBox
    {
        private Font oldFont = null;
        private Boolean waterMarkTextEnabled = false;

        #region Attributes 
            private Color _waterMarkColor = Color.Gray;
            public Color WaterMarkColor
            {
                get { return _waterMarkColor; }
                set { _waterMarkColor = value; Invalidate();/*thanks to Bernhard Elbl
                                                              for Invalidate()*/ }
            }

            private string _waterMarkText = "Water Mark";
            public string WaterMarkText
            {
                get { return _waterMarkText; }
                set { _waterMarkText = value; Invalidate(); }
            }
        #endregion

        //Default constructor
        public WaterMarkTextBox()
        {
            JoinEvents(true);
        }

        //Override OnCreateControl ... thanks to  "lpgray .. codeproject guy"
        protected override void OnCreateControl() 
        { 
            base.OnCreateControl();
            WaterMark_Toggel(null, null); 
        }

        //Override OnPaint
        protected override void OnPaint(PaintEventArgs args)
        {
            // Use the same font that was defined in base class
            System.Drawing.Font drawFont = new System.Drawing.Font(Font.FontFamily,
                Font.Size, Font.Style, Font.Unit);
            //Create new brush with gray color or 
            SolidBrush drawBrush = new SolidBrush(WaterMarkColor);//use Water mark color
            //Draw Text or WaterMark
            args.Graphics.DrawString((waterMarkTextEnabled ? WaterMarkText : Text),
                drawFont, drawBrush, new PointF(0.0F, 0.0F));
            base.OnPaint(args);
        }

        private void JoinEvents(Boolean join)
        {
            if (join)
            {
                this.TextChanged += new System.EventHandler(this.WaterMark_Toggel);
                this.LostFocus += new System.EventHandler(this.WaterMark_Toggel);
                this.FontChanged += new System.EventHandler(this.WaterMark_FontChanged);
                //No one of the above events will start immeddiatlly 
                //TextBox control still in constructing, so,
                //Font object (for example) couldn't be catched from within
                //WaterMark_Toggle
                //So, call WaterMark_Toggel through OnCreateControl after TextBox
                //is totally created
                //No doupt, it will be only one time call

                //Old solution uses Timer.Tick event to check Create property
            }
        }

        private void WaterMark_Toggel(object sender, EventArgs args )
        {
            if (this.Text.Length <= 0)
                EnableWaterMark();
            else
                DisbaleWaterMark();
        }

        private void EnableWaterMark()
        {
            //Save current font until returning the UserPaint style to false (NOTE:
            //It is a try and error advice)
            oldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style,
               Font.Unit);
            //Enable OnPaint event handler
            this.SetStyle(ControlStyles.UserPaint, true);
            this.waterMarkTextEnabled = true;
            //Triger OnPaint immediatly
            Refresh();
        }

        private void DisbaleWaterMark()
        {
            //Disbale OnPaint event handler
            this.waterMarkTextEnabled = false;
            this.SetStyle(ControlStyles.UserPaint, false);
            //Return back oldFont if existed
            if(oldFont != null)
                this.Font = new System.Drawing.Font(oldFont.FontFamily, oldFont.Size,
                    oldFont.Style, oldFont.Unit);
        }

        private void WaterMark_FontChanged(object sender, EventArgs args)
        {
            if (waterMarkTextEnabled)
            {
                oldFont = new System.Drawing.Font(Font.FontFamily,Font.Size,Font.Style,
                    Font.Unit);
                Refresh();
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    根据@Pooven 的回答(谢谢!),我创建了这个类。对我有用。

    /// <summary>
    /// A textbox that supports a watermak hint.
    /// </summary>
    public class WatermarkTextBox : TextBox
    {
        /// <summary>
        /// The text that will be presented as the watermak hint
        /// </summary>
        private string _watermarkText = "Type here";
        /// <summary>
        /// Gets or Sets the text that will be presented as the watermak hint
        /// </summary>
        public string WatermarkText
        {
            get { return _watermarkText; }
            set { _watermarkText = value; }
        }
    
        /// <summary>
        /// Whether watermark effect is enabled or not
        /// </summary>
        private bool _watermarkActive = true;
        /// <summary>
        /// Gets or Sets whether watermark effect is enabled or not
        /// </summary>
        public bool WatermarkActive
        {
            get { return _watermarkActive; }
            set { _watermarkActive = value; }
        }
    
        /// <summary>
        /// Create a new TextBox that supports watermak hint
        /// </summary>
        public WatermarkTextBox()
        {
            this._watermarkActive = true;
            this.Text = _watermarkText;
            this.ForeColor = Color.Gray;
    
            GotFocus += (source, e) =>
            {
                RemoveWatermak();
            };
    
            LostFocus += (source, e) =>
            {
                ApplyWatermark();
            };
    
        }
    
        /// <summary>
        /// Remove watermark from the textbox
        /// </summary>
        public void RemoveWatermak()
        {
            if (this._watermarkActive)
            {
                this._watermarkActive = false;
                this.Text = "";
                this.ForeColor = Color.Black;
            }
        }
    
        /// <summary>
        /// Applywatermak immediately
        /// </summary>
        public void ApplyWatermark()
        {
            if (!this._watermarkActive && string.IsNullOrEmpty(this.Text)
                || ForeColor == Color.Gray ) 
            {
                this._watermarkActive = true;
                this.Text = _watermarkText;
                this.ForeColor = Color.Gray;
            }
        }
    
        /// <summary>
        /// Apply watermak to the textbox. 
        /// </summary>
        /// <param name="newText">Text to apply</param>
        public void ApplyWatermark(string newText)
        {
            WatermarkText = newText;
            ApplyWatermark();
        }
    
    }
    

    【讨论】:

      【解决方案4】:
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
        const int EM_SETCUEBANNER = 0x1501; 
      
        public Form1()
        {
            InitializeComponent();
            SendMessage(textBox1.Handle, EM_SETCUEBANNER, 1, "Username");
            SendMessage(textBox2.Handle, EM_SETCUEBANNER, 1, "Password");
        }
      

      【讨论】:

        【解决方案5】:

        我这个学期刚开始学习 C#,所以我不是专家,但这对我有用: (这是使用windows窗体)

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.SelectionStart = 0;  //This keeps the text
            textBox1.SelectionLength = 0; //from being highlighted
            textBox1.ForeColor = Color.Gray;
        }
        
        private void textBox_MouseMove(object sender, MouseEventArgs e)
        {
            Cursor.Current = Cursors.IBeam; //Without this the mouse pointer shows busy
        }
        
        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (textBox1.Text.Equals("Type here...") == true)
            {
                textBox1.Text = "";
                textBox1.ForeColor = Color.Black;
            }
        }
        
        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            if (textBox1.Text.Equals(null) == true || textBox1.Text.Equals("") == true)
            {
                textBox1.Text = "Type here...";
                textBox1.ForeColor = Color.Gray;
            }
        }
        

        【讨论】:

          【解决方案6】:

          产生与 HTML 水印相似的输出

          这是我的文本框“水印”或“预览”文本的代码 - 效果很好!使用 Windows 窗体应用程序。

          注意:这个例子有 3 个文本框,每个文本框都有下面的方法分别用于“鼠标离开”事件和“鼠标进入”事件。

          private void textBoxFav_Leave(object sender, EventArgs e) {
            TextBox textbox = (TextBox)sender;
            if (String.IsNullOrWhiteSpace(textbox.Text)) {
              textbox.ForeColor = Color.Gray;
              if (textbox.Name == "textBoxFavFood") {
                textbox.Text = "Favorite Food";
              }
              else if (textbox.Name == "textBoxFavDrink") {
                textbox.Text = "Favorite Drink";
              }
              else if (textbox.Name == "textBoxFavDesert") {
                textbox.Text = "Favorite Desert";
              }
            }
            else {
              textbox.ForeColor = Color.Black;
            }
          }
          
          private void textBoxFav_Enter(object sender, EventArgs e) {
            TextBox textbox = (TextBox)sender;
            if (textbox.Text == "Favorite Food" || textbox.Text == "Favorite Drink" || textbox.Text == "Favorite Desert") {
              textbox.Text = "";
              textbox.ForeColor = Color.Black;
            }
          }
          

          【讨论】:

            【解决方案7】:

            处理失去焦点事件,如果属性 Text 为空,则使用默认字符串填充它。

            【讨论】:

            • 我还处理了点击事件来清除文本框文本。
            【解决方案8】:

            如果这是 ASP.NET(而不是 winforms),您可以这样做:

            如果您使用的是 jQuery,请将其添加到准备好的文档中(或者您初始化页面):

            var $textbox = $("textbox selector"); // assumes you select a single text box
            if ($textbox.val() == "") {
               $textbox.val("Type here to...");
               $textbox.one('focus', function() {
                 $(this).attr('value', '');
               });
            }
            

            如果要选择多个文本框,则需要进行一些小的重构(将 if 语句放在元素上的 each 内)。

            【讨论】:

              【解决方案9】:

              在 C# 的最后一个版本中,TextBox 具有属性 PlaceholderText,它可以正常工作。所以你只需要设置“Type here...”作为这个属性的值。

              【讨论】:

              • 认为您需要向我们展示该链接的 MSDN 链接,因为我无法在文档中找到任何备份它的内容..
              • Windows 窗体中 TextBox 控件上的 PlaceholderText 属性从 .NET Core 3.0 或 .NET 5.0 开始可用。
              【解决方案10】:

              根据 Ahmed Soliman Flasha 的回答,使用以下课程:

              public class TextBoxHint : TextBox
              {
                  string _hint;
              
                  [Localizable(true)]
                  public string Hint
                  {
                      get { return _hint; }
                      set { _hint = value; OnHintChanged(); }
                  }
              
                  protected virtual void OnHintChanged()
                  {
                      SendMessage(this.Handle, EM_SETCUEBANNER, 1, _hint);
                  }     
              
                  const int EM_SETCUEBANNER = 0x1501;
              
                  [DllImport("user32.dll", CharSet = CharSet.Auto)]
                  private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
              }
              

              【讨论】:

                【解决方案11】:

                您可以将字符串“Type here”绘制到文本框背景直到它为空

                【讨论】:

                  【解决方案12】:

                  如果这是针对 ASP.NET 的,那么您可以尝试TextBoxWatermark。

                  如果这是用于 Windows 窗体,则已在 SO 中回答 here。

                  【讨论】:

                    【解决方案13】:

                    为什么要使用 OnTextChanged? 我建议在 TextBox 获得焦点时删除文本“在此处输入”。 当控件失去焦点并且没有输入文本时,您可以再次显示文本。

                    同样的结果,不需要复杂的逻辑。

                    【讨论】:

                      【解决方案14】:

                      如果您想避免控件调整大小问题和数据绑定问题并使代码更简单(好吧,这是有问题的),您可以只使用标签并切换它的可见性。那么

                          private void FilterComboBox_GotFocus(object sender, EventArgs e)
                          {
                              FilterWatermarkLabel.Visible = false;
                          }
                      
                          private void FilterComboBox_LostFocus(object sender, EventArgs e)
                          {
                              if (!FilterWatermarkLabel.Visible && string.IsNullOrEmpty(FilterComboBox.Text))
                              {
                                  FilterWatermarkLabel.Visible = true;
                              }
                          }
                      

                      这里有另一种处理图像并避免数据绑定问题的方法 https://msdn.microsoft.com/en-us/library/bb613590(v=vs.100).aspx

                      【讨论】:

                        【解决方案15】:

                        基于@Joel 的回答。我修复了他的课程(感谢基础!)

                        /// <summary>
                        /// A textbox that supports a watermak hint.
                        /// Based on: https://stackoverflow.com/a/15232752
                        /// </summary>
                        public class WatermarkTextBox : TextBox
                        {
                            /// <summary>
                            /// The text that will be presented as the watermak hint
                            /// </summary>
                            private string _watermarkText;
                        
                            /// <summary>
                            /// Gets or Sets the text that will be presented as the watermak hint
                            /// </summary>
                            public string WatermarkText
                            {
                                get { return _watermarkText; }
                                set { _watermarkText = value; }
                            }
                        
                            /// <summary>
                            /// Whether watermark effect is enabled or not
                            /// </summary>
                            private bool _watermarkActive;
                            /// <summary>
                            /// Gets or Sets whether watermark effect is enabled or not
                            /// </summary>
                            public bool WatermarkActive
                            {
                                get { return _watermarkActive; }
                                set { _watermarkActive = value; }
                            }
                        
                            /// <summary>
                            /// Create a new TextBox that supports watermak hint
                            /// </summary>
                            public WatermarkTextBox()
                            {
                                this.WatermarkActive = _watermarkActive;
                                this.Text = _watermarkText;
                            }
                        
                            protected override void OnCreateControl()
                            {
                                base.OnCreateControl();
                                if (this.WatermarkActive)
                                    CheckWatermark();
                            }
                        
                            protected override void OnGotFocus(EventArgs e)
                            {
                                base.OnGotFocus(e);
                                CheckWatermark();
                            }
                        
                            protected override void OnLostFocus(EventArgs e)
                            {
                                base.OnLostFocus(e);
                                CheckWatermark();
                            }        
                        
                            public void CheckWatermark()
                            {
                                if ((this.WatermarkActive) && String.IsNullOrWhiteSpace(this.Text))
                                {
                                    ForeColor = Color.Gray;
                                    this.Text = _watermarkText;
                                }
                                else if ((this.WatermarkActive) && (!String.IsNullOrWhiteSpace(this.Text)))
                                {
                                    if (this.Text == _watermarkText)
                                        this.Text = "";
                                    ForeColor = Color.Black;
                                }
                                else
                                    ForeColor = Color.Black;
                            }
                        }
                        

                        【讨论】:

                          【解决方案16】:

                          在用户将文本输入文本框之前显示“在此处键入...”是当今众所周知的可用性功能。如何在 C# 中实现这一功能?

                          1. 将 textbox.text 设置为“Type here to ...”

                          2. 创建一个事件,比如 box_click()

                          3. -->把这段代码放到你的方法中

                            private void box_Click(object sender, EventArgs e)
                            {
                                Textbox b = (Textbox)sender;
                                b.Text = null;
                            }
                            
                          4. 现在将此方法分配给文本框的“Enter”事件(可能是一个或多个)

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2019-02-07
                            • 1970-01-01
                            • 2021-12-06
                            • 2016-03-24
                            • 2013-12-05
                            • 1970-01-01
                            • 2012-02-22
                            相关资源
                            最近更新 更多