将占位符文本添加到文本框
我正在寻找一种方法来添加占位符文本到一个文本框,就像你可以用HTML5中的文本框。
也就是说,如果文本框没有文本,那么它会在Enter some text here
添加文本Enter some text here
,当用户点击它时占位符文本消失,并允许用户input自己的文本,如果文本框失去焦点,并且仍然没有文字然后占位符被添加回到文本框。
难道这不是这样的:
Textbox myTxtbx = new Textbox(); myTxtbx.Text = "Enter text here..."; myTxtbx.GotFocus += GotFocus.EventHandle(RemoveText); myTxtbx.LostFocus += LostFocus.EventHandle(AddText); public RemoveText(object sender, EventArgs e) { myTxtbx.Text = ""; } public AddText(object sender, EventArgs e) { if(String.IsNullOrWhiteSpace(myTxtbx.Text)) myTxtbx.Text = "Enter text here..."; }
这只是伪代码,但概念在那里。
你可以使用这个,这对我来说是非常简单的解决scheme。
<Style x:Key="placeHolder" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Grid> <TextBox Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" /> <TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Setter Property="Foreground" Value="Transparent"/> <Style.Triggers> <DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value=""> <Setter Property="Foreground" Value="LightGray"/> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
用法:
<TextBox Style="{StaticResource placeHolder}" Tag="Name of customer" Width="150" Height="24"/>
为了设置和删除占位符文本,可以使用Windows SendMessage函数将EM_SETCUEBANNER
消息发送到我们的文本框来为我们完成工作,而不是处理焦点input和焦点离开事件。
这可以通过两个简单的步骤完成。 首先我们需要公开Windows SendMessage
函数。
private 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);
然后只需使用我们的文本框的句柄EM_SETCUEBANNER的值和我们想要设置的文本调用方法。
SendMessage(textBox1.Handle, EM_SETCUEBANNER, 0, "Username"); SendMessage(textBox2.Handle, EM_SETCUEBANNER, 0, "Password");
参考: 设置文本框的占位符文本(提示文本)
添加这个类你的项目,并build立你的解决scheme。 在Visual Studio上单击工具箱,您将看到一个名为PlaceholderTextBox的新文本框。 在表单devise中删除当前的文本框,并用PlaceHolderTextBoxreplace。
PlaceHolderTextBox有一个属性PlaceHolderText。 设置你想要的任何文本,并有美好的一天:)
public class PlaceHolderTextBox : TextBox { bool isPlaceHolder = true; string _placeHolderText; public string PlaceHolderText { get { return _placeHolderText; } set { _placeHolderText = value; setPlaceholder(); } } //when the control loses focus, the placeholder is shown private void setPlaceholder() { if (string.IsNullOrEmpty(this.Text)) { this.Text = PlaceHolderText; this.ForeColor = Color.Gray; this.Font = new Font(this.Font, FontStyle.Italic); isPlaceHolder = true; } } //when the control is focused, the placeholder is removed private void removePlaceHolder() { if (isPlaceHolder) { this.Text = ""; this.ForeColor = System.Drawing.SystemColors.WindowText; this.Font = new Font(this.Font, FontStyle.Regular); isPlaceHolder = false; } } public PlaceHolderTextBox() { GotFocus += removePlaceHolder; LostFocus += setPlaceholder; } private void setPlaceholder(object sender, EventArgs e) { setPlaceholder(); } private void removePlaceHolder(object sender, EventArgs e) { removePlaceHolder(); } }
附加属性的救援:
public static class TextboxExtensions { public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached( "Placeholder", typeof(string), typeof(TextboxExtensions), new PropertyMetadata(default(string), propertyChangedCallback: PlaceholderChanged)); private static void PlaceholderChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) { var tb = dependencyObject as TextBox; if(tb == null) return; tb.LostFocus -= OnLostFocus; tb.GotFocus -= OnGotFocus; if (args.NewValue != null) { tb.GotFocus += OnGotFocus; tb.LostFocus += OnLostFocus; } } private static void OnLostFocus(object sender, RoutedEventArgs routedEventArgs) { var tb = sender as TextBox; if (string.IsNullOrEmpty(tb.Text) || string.IsNullOrWhiteSpace(tb.Text)) { tb.Text = GetPlaceholder(tb); } } private static void OnGotFocus(object sender, RoutedEventArgs routedEventArgs) { var tb = sender as TextBox; var ph = GetPlaceholder(tb); if (tb.Text == ph) { tb.Text = string.Empty; } } [AttachedPropertyBrowsableForType(typeof(TextBox))] public static void SetPlaceholder(DependencyObject element, string value) { element.SetValue(PlaceholderProperty, value); } [AttachedPropertyBrowsableForType(typeof(TextBox))] public static string GetPlaceholder(DependencyObject element) { return (string) element.GetValue(PlaceholderProperty); } }
用法:
<TextBox Text="hi" local:TextboxExtensions.Placeholder="Hello there"></TextBox>
你可以得到默认的Template
,通过叠加一个TextBlock
修改它,并使用一个Style
来添加触发器,隐藏并以正确的状态显示它。
这意味着你有一个button,允许你做一个动作,比如login或者其他的东西。 在执行操作之前,请检查文本框是否被填充。如果不是,将replace文本
private void button_Click(object sender, EventArgs e) { string textBoxText = textBox.Text; if (String.IsNullOrWhiteSpace(textBoxText)) { textBox.Text = "Fill in the textbox"; } } private void textBox_Enter(object sender, EventArgs e) { TextBox currentTextbox = sender as TextBox; if (currentTextbox.Text == "Fill in the textbox") { currentTextbox.Text = ""; } }
这是一种俗气,但检查文本的价值,你给它是最好的,我可以做atm,不是很好的C#获得更好的解决scheme。
基于ExceptionLimeCat的答案,一个改进:
Color farbe; string ph = "Placeholder-Text"; private void Form1_Load(object sender, EventArgs e) { farbe = myTxtbx.ForeColor; myTxtbx.GotFocus += RemoveText; myTxtbx.LostFocus += AddText; myTxtbx.Text = ph; } public void RemoveText(object sender, EventArgs e) { myTxtbx.ForeColor = farbe; if (myTxtbx.Text == ph) myTxtbx.Text = ""; } public void AddText(object sender, EventArgs e) { if (String.IsNullOrWhiteSpace(myTxtbx.Text)) { myTxtbx.ForeColor = Color.Gray; myTxtbx.Text = ph; } }
虽然使用EM_SETCUEBANNER
消息可能是最简单的,但我不喜欢的是当控件获得焦点时,占位符文本消失。 当我填写表格时,这是我的宠物。 我必须点击它来记住该字段的用途。
所以这里是WinForms的另一个解决scheme。 它在控件之上叠加一个Label
,只有当用户开始input时才会消失。
这当然不是防弹的。 它接受任何Control
,但我只testing一个TextBox
。 可能需要修改才能使用某些控件。 该方法返回Label
控件,以防在特定情况下需要修改它,但可能永远不需要。
像这样使用它:
SetPlaceholder(txtSearch, "Type what you're searching for");
这里是方法:
/// <summary> /// Sets placeholder text on a control (may not work for some controls) /// </summary> /// <param name="control">The control to set the placeholder on</param> /// <param name="text">The text to display as the placeholder</param> /// <returns>The newly-created placeholder Label</returns> public static Label SetPlaceholder(Control control, string text) { var placeholder = new Label { Text = text, Font = control.Font, ForeColor = Color.Gray, BackColor = Color.Transparent, Cursor = Cursors.IBeam, Margin = Padding.Empty, //get rid of the left margin that all labels have FlatStyle = FlatStyle.System, AutoSize = false, //Leave 1px on the left so we can see the blinking cursor Size = new Size(control.Size.Width - 1, control.Size.Height), Location = new Point(control.Location.X + 1, control.Location.Y) }; //when clicking on the label, pass focus to the control placeholder.Click += (sender, args) => { control.Focus(); }; //disappear when the user starts typing control.TextChanged += (sender, args) => { placeholder.Visible = string.IsNullOrEmpty(control.Text); }; //stay the same size/location as the control EventHandler updateSize = (sender, args) => { placeholder.Location = new Point(control.Location.X + 1, control.Location.Y); placeholder.Size = new Size(control.Size.Width - 1, control.Size.Height); }; control.SizeChanged += updateSize; control.LocationChanged += updateSize; control.Parent.Controls.Add(placeholder); placeholder.BringToFront(); return placeholder; } }
我想出了一个适用于我的方法,但只是因为我愿意使用文本框名称作为占位符。 见下文。
public TextBox employee = new TextBox(); private void InitializeHomeComponent() { // //employee // this.employee.Name = "Caller Name"; this.employee.Text = "Caller Name"; this.employee.BackColor = System.Drawing.SystemColors.InactiveBorder; this.employee.Location = new System.Drawing.Point(5, 160); this.employee.Size = new System.Drawing.Size(190, 30); this.employee.TabStop = false; this.Controls.Add(employee); // I loop through all of my textboxes giving them the same function foreach (Control C in this.Controls) { if (C.GetType() == typeof(System.Windows.Forms.TextBox)) { C.GotFocus += g_GotFocus; C.LostFocus += g_LostFocus; } } } private void g_GotFocus(object sender, EventArgs e) { var tbox = sender as TextBox; tbox.Text = ""; } private void g_LostFocus(object sender, EventArgs e) { var tbox = sender as TextBox; if (tbox.Text == "") { tbox.Text = tbox.Name; } }
这不是我的代码,但我使用它很多,它的作品完美… XAML只
<TextBox x:Name="Textbox" Height="23" Margin="0,17,18.8,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" HorizontalAlignment="Right" <TextBlock x:Name="Placeholder" IsHitTestVisible="False" TextWrapping="Wrap" Text="Placeholder Text" VerticalAlignment="Top" Margin="0,20,298.8,0" Foreground="DarkGray" HorizontalAlignment="Right" Width="214"> <TextBlock.Style> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Visibility" Value="Collapsed"/> <Style.Triggers> <DataTrigger Binding="{Binding Text, ElementName=Textbox}" Value=""> <Setter Property="Visibility" Value="Visible"/> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; namespace App_name { public class CustomTextBox : TextBox { private string Text_ = ""; public CustomTextBox() : base() {} public string setHint { get { return Text_; } set { Text_ = value; } } protected override void OnGotFocus(RoutedEventArgs e) { base.OnGotFocus(e); if (Text_.Equals(this.Text)) this.Clear(); } protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); if (String.IsNullOrWhiteSpace(this.Text)) this.Text = Text_; } } } > xmlns:local="clr-namespace:app_name" > <local:CustomTextBox > x:Name="id_number_txt" > Width="240px" > Height="auto"/>
试试下面的代码:
<TextBox x:Name="InvoiceDate" Text="" Width="300" TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" /> <TextBlock IsHitTestVisible="False" Text="Men att läsa" Width="300" TextAlignment="Left" Height="30" Grid.Row="0" Grid.Column="3" Grid.ColumnSpan="2" Padding="5, 5, 5, 5" Foreground="LightGray"> <TextBlock.Style> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Visibility" Value="Collapsed"/> <Style.Triggers> <DataTrigger Binding="{Binding Text, ElementName=InvoiceDate}" Value=""> <Setter Property="Visibility" Value="Visible"/> </DataTrigger> <DataTrigger Binding="{Binding ElementName=InvoiceDate, Path=IsFocused}" Value="True"> <Setter Property="Visibility" Value="Collapsed"/> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>
txtUsuario.Attributes.Add(“placeholder”,“Texto”);
你也可以这样做,当鼠标点击,让我们假设你的占位符文本是“User_Name”
private void textBox1_MouseClick(object sender, MouseEventArgs e) { if(textBox1.Text == "User_Name") textBox1.Text = ""; }
public void Initialize() { SetPlaceHolder(loginTextBox, " Логин "); SetPlaceHolder(passwordTextBox, " Пароль "); } public void SetPlaceHolder(Control control, string PlaceHolderText) { control.Text = PlaceHolderText; control.GotFocus += delegate(object sender, EventArgs args) { if (control.Text == PlaceHolderText) { control.Text = ""; } }; control.LostFocus += delegate(object sender, EventArgs args){ if (control.Text.Length == 0) { control.Text = PlaceHolderText; } }; }
我没有使用TextBox的.Text属性,而是用占位符叠加了一个TextBlock。 我无法使用.Text属性,因为这绑定到一个事件。
XAML:
<Canvas Name="placeHolderCanvas"> <TextBox AcceptsReturn="True" Name="txtAddress" Height="50" Width="{Binding ActualWidth, ElementName=placeHolderCanvas}" Tag="Please enter your address"/> </Canvas>
VB.NET
Public Shared Sub InitPlaceholder(canvas As Canvas) Dim txt As TextBox = canvas.Children.OfType(Of TextBox).First() Dim placeHolderLabel = New TextBlock() With {.Text = txt.Tag, .Foreground = New SolidColorBrush(Color.FromRgb(&H77, &H77, &H77)), .IsHitTestVisible = False} Canvas.SetLeft(placeHolderLabel, 3) Canvas.SetTop(placeHolderLabel, 1) canvas.Children.Add(placeHolderLabel) AddHandler txt.TextChanged, Sub() placeHolderLabel.Visibility = If(txt.Text = "", Visibility.Visible, Visibility.Hidden) End Sub
结果:
你也可以这样试试
调用该函数
TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");
写这个函数
private void TextboxPlaceHolder(Control control, string PlaceHolderText) { control.Text = PlaceHolderText; control.GotFocus += delegate (object sender, EventArgs args) { if (cusmode == false) { control.Text = control.Text == PlaceHolderText ? string.Empty : control.Text; //IF Focus TextBox forecolor Black control.ForeColor = Color.Black; } }; control.LostFocus += delegate (object sender, EventArgs args) { if (string.IsNullOrWhiteSpace(control.Text) == true) { control.Text = PlaceHolderText; //If not focus TextBox forecolor to gray control.ForeColor = Color.Gray; } }; }
在这里我带着这个由@Kemal Karadag启发的解决scheme。
我注意到,这里发布的每个解决scheme都依赖于重点,
虽然我希望占位符是Google Chrome中标准HTML占位符的确切克隆。
当箱子聚焦时,而不是隐藏/显示占位符,
我根据框的文本长度隐藏/显示占位符:
如果该框为空,则显示占位符,如果在框中键入,则占位符消失。
由于它是从一个标准的TextBoxinheritance的,你可以在你的工具箱中find它!
using System; using System.Drawing; using System.Windows.Forms; public class PlaceHolderTextBox : TextBox { private bool isPlaceHolder = true; private string placeHolderText; public string PlaceHolderText { get { return placeHolderText; } set { placeHolderText = value; SetPlaceholder(); } } public PlaceHolderTextBox() { TextChanged += OnTextChanged; } private void SetPlaceholder() { if (!isPlaceHolder) { this.Text = placeHolderText; this.ForeColor = Color.Gray; isPlaceHolder = true; } } private void RemovePlaceHolder() { if (isPlaceHolder) { this.Text = this.Text[0].ToString(); // Remove placeHolder text, but keep the character we just entered this.Select(1, 0); // Place the caret after the character we just entered this.ForeColor = System.Drawing.SystemColors.WindowText; isPlaceHolder = false; } } private void OnTextChanged(object sender, EventArgs e) { if (this.Text.Length == 0) { SetPlaceholder(); } else { RemovePlaceHolder(); } } }