Agregar texto de marcador de posición al cuadro de texto

147

Estoy buscando una manera de agregar texto de marcador de posición a un cuadro de texto como puede hacerlo con un cuadro de texto en html5.

Es decir, si el cuadro de texto no tiene texto, entonces agrega el texto Enter some text here, cuando el usuario hace clic en él, el texto del marcador de posición desaparece y le permite al usuario ingresar su propio texto, y si el cuadro de texto pierde el foco y aún no hay texto, entonces el marcador de posición es agregado de nuevo al cuadro de texto.

Boardy
fuente
44
No utilice la propiedad de texto para el texto de marcador de posición. Interferirá con la unión. Use AdornerDecorator ( msdn.microsoft.com/en-us/library/… )
Pavel Voronin
2
Eche un vistazo a stackoverflow.com/questions/833943/…
SepehrM
55
Solo un FYI: marca de agua, también conocido como texto de pista, también conocido como marcador de posición, también conocido como banner de referencia . Todos estos términos tienen la misma intención.
RBT

Respuestas:

91

¿No sería eso algo así?

Textbox myTxtbx = new Textbox();
myTxtbx.Text = "Enter text here...";

myTxtbx.GotFocus += GotFocus.EventHandle(RemoveText);
myTxtbx.LostFocus += LostFocus.EventHandle(AddText);

public void RemoveText(object sender, EventArgs e)
{
    if (myTxtbx.Text == "Enter text here...") 
    {
     myTxtbx.Text = "";
    }
}

public void AddText(object sender, EventArgs e)
{
    if (string.IsNullOrWhiteSpace(myTxtbx.Text))
        myTxtbx.Text = "Enter text here...";
}

Eso es solo pseudocódigo, pero el concepto está ahí.

ExceptionLimeCat
fuente
Gracias, esperaba que hubiera algún tipo de XAML que se pueda usar para crear el marcador de posición. Gracias por su ayuda
Boardy
1
Esperaba encontrar una solución que mantuviera el texto del marcador de posición en el cuadro de texto hasta que el usuario ingresara el texto. Parece que eso funcionaría mejor.
Usuarios de DROP TABLE
66
Esto funcionará PERO si el valor del cuadro de texto está vinculado a la fuente, entonces probablemente tenga un problema.
Pavel Voronin
1
Esta es una buena solución simple, lo único es que incluso después de ingresar texto, si el usuario vuelve a hacer clic en el cuadro de texto (por ejemplo, para agregar más texto o eliminar algunos caracteres), todo el cuadro de texto perderá el valor ingresado
Bibaswann Bandyopadhyay
2
RemoveTexty el AddTextmétodo debe ser public void, falta vacío . Y como ha dicho @BibaswannBandyopadhyay, el RemoveTextmétodo podría ser este:if (myTxtbx.Text == "Enter text here...") {myTxtbx.Text = "";}
KaKa
91

Puede usar esto, está funcionando para mí y es una solución extremadamente simple.

    <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>

Uso:

<TextBox Style="{StaticResource placeHolder}" Tag="Name of customer" Width="150" Height="24"/>

‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎

MacGile
fuente
1
Hola @MacGile, modifiqué tu gran solución, porque necesito el enlace bidireccional entre la propiedad de texto original y la propiedad textSource.Text.
Gábor Plesz
1
@Rob lo puso en un diccionario de recursos. Window.Recursos, etc.
Brian
66
Para problemas de enfoque, agregue esto: <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusManager.FocusedElement" TargetName="textSource" Value="{Binding RelativeSource={RelativeSource Self}}" /> </Trigger> </ControlTemplate.Triggers>
Cihan Yakar
1
Agregaría las TextWrapping="wrap"dos etiquetas TextBox en el Estilo, en caso de que desee hacer un TextBox de varias líneas con texto de marcador de posición como lo hice yo.
jpcguy89
1
@Sachin He arreglado mi propiedad MaxLenght. El problema es que un cuadro de texto se reemplaza por 2 cuadros de texto. Uno para la entrada y otro para el marcador de posición. Para propiedades fix roto sólo tiene que añadir a la primera caja de texto así: <TextBox Text="{Binding Path=Text, RelativeSource=RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" MaxLength="{TemplateBinding MaxLength}" />. En su caso, probablemente necesite agregarAcceptsReturn="{TemplateBinding AcceptsReturn}"
ColmanJ
47

En lugar de manejar los eventos de entrada y salida de foco para establecer y eliminar el texto del marcador de posición, es posible usar la función Enviar EM_SETCUEBANNERmensaje de Windows para enviar un mensaje a nuestro cuadro de texto para hacer el trabajo por nosotros.

Esto se puede hacer con dos sencillos pasos. Primero necesitamos exponer la SendMessagefunción de Windows .

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);

Luego simplemente llame al método con el identificador de nuestro cuadro de texto, el valor de EM_SETCUEBANNER y el texto que queremos establecer.

SendMessage(textBox1.Handle, EM_SETCUEBANNER, 0, "Username");
SendMessage(textBox2.Handle, EM_SETCUEBANNER, 0, "Password");

Referencia: Establecer texto de marcador de posición para el cuadro de texto (texto de referencia)

Abdullah Qudeer
fuente
10
Nota: esto no funciona para WPF . Ver: stackoverflow.com/questions/5054872/…
ArtOfCode
La mejor respuesta aquí, pero tenga en cuenta que Form_Load es demasiado temprano, tuve que esperar hasta Form_Shown antes de que funcionara.
Jay Croghan
Lo único que odio de esto es que el texto desaparece tan pronto como el control obtiene el foco, lo que significa que si no captó lo que dijo (y es importante), debe hacer clic fuera para ver el texto del marcador de posición nuevamente . Agregué otra respuesta para agregar un marcador de posición que desaparece solo después de que el usuario comienza a escribir.
Gabriel Luci
19

Agregue a esta clase su proyecto y cree su solución. Haga clic en Toolbox en Visual Studio, verá un nuevo componente de cuadro de texto llamado PlaceholderTextBox. Elimine su cuadro de texto actual en el formulario designado y reemplácelo con PlaceHolderTextBox.

ingrese la descripción de la imagen aquí

PlaceHolderTextBox tiene una propiedad PlaceHolderText. Establezca el texto que desee y que tenga un buen día :)

public class PlaceHolderTextBox : TextBox
{

    bool isPlaceHolder = true;
    string _placeHolderText;
    public string PlaceHolderText
    {
        get { return _placeHolderText; }
        set
        {
            _placeHolderText = value;
            setPlaceholder();
        }
    }

    public new string Text
    {
        get => isPlaceHolder ? string.Empty : base.Text;
        set => base.Text = value;
    }

    //when the control loses focus, the placeholder is shown
    private void setPlaceholder()
    {
        if (string.IsNullOrEmpty(base.Text))
        {
            base.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)
        {
            base.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();
    }
}
Kemal Karadag
fuente
11
Cuando algún otro control actúa sobre el valor de la Textpropiedad (por ejemplo, un cuadro de texto utilizado para filtrar una lista), el marcador de posición se utilizará para filtrar. El valor del marcador de posición solo debe usarse para mostrar, por lo tanto, no es una buena idea reemplazar la Textpropiedad temporalmente.
Roland Illig
1
Solución ordenada, me gusta. Agregaría estos usos en la parte superior de la clase, para que funcione: ¡ using System; using System.Drawing; using System.Windows.Forms;Gracias por esto!
Eldoïr
18

Este no es mi código, pero lo uso mucho y funciona perfecto ... SOLO XAML

<TextBox x:Name="Textbox" Height="23" Margin="0,17,18.8,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" HorizontalAlignment="Right" ></TextBox>

<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>
Jaun Lloyd
fuente
1
Funciona a las mil maravillas, y si agrega un disparador a IsFocused reemplazando DataTriggerel siguiente MultiDataTrigger, funciona en mi humilde opinión:<MultiDataTrigger><MultiDataTrigger.Conditions><Condition Binding="{Binding IsFocused, ElementName=Textbox}" Value="false" /><Condition Binding="{Binding Text, ElementName=Textbox}" Value="" /></MultiDataTrigger.Conditions><MultiDataTrigger.Setters> <Setter Property="Visibility" Value="Visible"/></MultiDataTrigger.Setters></MultiDataTrigger>
Akku
9

Propiedades adjuntas al rescate:

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;
        }

        SetPlaceholder(dependencyObject, args.NewValue as string);

        if (!tb.IsFocused)
            ShowPlaceholder(tb);
    }

    private static void OnLostFocus(object sender, RoutedEventArgs routedEventArgs)
    {
        ShowPlaceholder(sender as TextBox);
    }

    private static void OnGotFocus(object sender, RoutedEventArgs routedEventArgs)
    {
        HidePlaceholder(sender as TextBox);
    }

    [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);
    }

    private static void ShowPlaceholder(TextBox textBox)
    {
        if (string.IsNullOrWhiteSpace(textBox.Text))
        {
            textBox.Text = GetPlaceholder(textBox);
        }
    }

    private static void HidePlaceholder(TextBox textBox)
    {
        string placeholderText = GetPlaceholder(textBox);

        if (textBox.Text == placeholderText)
            textBox.Text = string.Empty;
    }
}

Uso:

<TextBox Text="hi" local:TextboxExtensions.Placeholder="Hello there"></TextBox>
Dbl
fuente
Gracias por proporcionar esta buena solución. Sin embargo, al usar su solución, se obtiene a) texto de marcador de posición negro en lugar de uno gris claro yb) no muestra texto de marcador de posición al inicio de la aplicación (pero después de enfocar y luego establecer el enfoque en otro lugar). ¿Te importaría mejorar tu respuesta a este respecto?
Yoda
1
@Yoda Si logro no olvidarlo hasta que llegue a casa, buscaré mejorarlo, sí, ¿por qué no
Dbl
1
Marcador de posición en blanco hasta enfocar / desenfocar fijo.
Sergey
1
@Yoda Hola, no me importa si se hace con cuidado y no rompe nada.
Sergey
1
@Yoda, lo siento, no he estado trabajando con WPF por un tiempo, ni siquiera lo tengo instalado en este momento. Puede agregar otra propiedad de dependencia nombrada PlaceholderColorcon typeof(Brush). Luego cambie la textBox.Foregroundpropiedad en el ShowPlaceholdermétodo y restaúrelo nuevamente en el HidePlaceholdermétodo.
Sergey
5

Si bien el uso del EM_SETCUEBANNERmensaje es probablemente más simple, una cosa que no me gusta es que el texto del marcador de posición desaparece cuando el control se enfoca. Ese es un motivo favorito mío cuando estoy completando formularios. Tengo que hacer clic para recordar para qué sirve el campo.

Así que aquí hay otra solución para WinForms. Superpone una Labelencima del control, que desaparece solo cuando el usuario comienza a escribir.

Ciertamente no es a prueba de balas. Acepta cualquiera Control, pero solo lo he probado con a TextBox. Puede necesitar modificaciones para trabajar con algunos controles. El método devuelve el Labelcontrol en caso de que necesite modificarlo un poco en un caso específico, pero puede que nunca sea necesario.

Úselo así:

SetPlaceholder(txtSearch, "Type what you're searching for");

Aquí está el método:

/// <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;
}
Gabriel Luci
fuente
4

Basado en la respuesta de ExceptionLimeCat, una mejora:

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;
    }
}
Vitalis Hommel
fuente
3

Esto significaría que tiene un botón que le permite realizar una acción, como iniciar sesión o algo así. Antes de realizar la acción, verifica si el cuadro de texto está lleno. De lo contrario, reemplazará el texto

 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 = "";
     }
 }

Es un poco cursi, pero verificar el texto por el valor que le está dando es lo mejor que puedo hacer en el cajero automático, no tan bueno en C # para obtener una mejor solución.

VJamie
fuente
2
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"/>
Saef Myth
fuente
Explique su respuesta en lugar de simplemente verter un montón de código en su respuesta.
Financia la demanda de Mónica el
1

Se me ocurrió un método que funcionó para mí, pero solo porque estaba dispuesto a usar el nombre del cuadro de texto como marcador de posición. Vea abajo.

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;
        }
    }
CBC_NS
fuente
1

Aquí vengo con esta solución inspirada en @Kemal Karadag.

Noté que cada solución publicada aquí se basa en el enfoque,

Si bien quería que mi marcador de posición fuera el clon exacto de un marcador de posición HTML estándar en Google Chrome.

En lugar de ocultar / mostrar el marcador de posición cuando el cuadro está enfocado,

Oculto / muestro el marcador de posición según la longitud del texto del cuadro:

Si el cuadro está vacío, se muestra el marcador de posición, y si escribe en el cuadro, el marcador de posición desaparece.

Como se hereda de un cuadro de texto estándar, ¡puede encontrarlo en su Caja de herramientas!

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();
        }
    }
}
Eldoir
fuente
0

Prueba el siguiente código:

<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>
Nalan Madheswaran
fuente
0

txtUsuario.Attributes.Add ("marcador de posición", "Texto");

Everton Luke
fuente
0

también puede hacerlo cuando el mouse hace clic, supongamos que el texto del marcador de posición es "Nombre_de_usuario"

 private void textBox1_MouseClick(object sender, MouseEventArgs e)
 {
     if(textBox1.Text == "User_Name")
          textBox1.Text = "";
 }
Adiii
fuente
0
    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;
            }
        };
    }
igorpauk
fuente
55
La pregunta ya está resuelta, ¿cuál es el valor agregado de esta respuesta? No hay explicación, agregue todo, intente explicarlo.
Jannik
0

En lugar de usar la propiedad .Text de un TextBox, superpuse un TextBlock con el marcador de posición. No pude usar la propiedad .Text porque estaba vinculada a un evento.

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

Resultado: ingrese la descripción de la imagen aquí

andy
fuente
0

También puedes intentarlo de esta manera ...

llama a la función

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

escribe esta función

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;
            }

        };
}
Ramgy Borja
fuente
0

hay MEJORES soluciones, pero la solución más fácil está aquí: establezca el texto del cuadro de texto en la cadena deseada y luego cree una función que elimine el texto, haga que esa función se active en el evento de enfoque de cuadro de texto.

Jared
fuente
0

Escribí un control personalizado reutilizable, tal vez pueda ayudar a alguien que necesite implementar múltiples cuadros de texto de marcador de posición en su proyecto.
Aquí está la clase personalizada con el ejemplo de implementación de una instancia, puede probar fácilmente pegando este código en un nuevo proyecto winforms usando VS:

namespace reusebleplaceholdertextbox
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // implementation
            CustomPlaceHolderTextbox myCustomTxt = new CustomPlaceHolderTextbox(
                "Please Write Text Here...", Color.Gray, new Font("ARIAL", 11, FontStyle.Italic)
                , Color.Black, new Font("ARIAL", 11, FontStyle.Regular)
                );

            myCustomTxt.Multiline = true;
            myCustomTxt.Size = new Size(200, 50);
            myCustomTxt.Location = new Point(10, 10);
            this.Controls.Add(myCustomTxt);
        }
    }

    class CustomPlaceHolderTextbox : System.Windows.Forms.TextBox
    {
        public string PlaceholderText { get; private set; }
        public Color PlaceholderForeColor { get; private set; }
        public Font PlaceholderFont { get; private set; }

        public Color TextForeColor { get; private set; }
        public Font TextFont { get; private set; }

        public CustomPlaceHolderTextbox(string placeholdertext, Color placeholderforecolor,
            Font placeholderfont, Color textforecolor, Font textfont)
        {
            this.PlaceholderText = placeholdertext;
            this.PlaceholderFont = placeholderfont;
            this.PlaceholderForeColor = placeholderforecolor;
            this.PlaceholderFont = placeholderfont;
            this.TextForeColor = textforecolor;
            this.TextFont = textfont;
            if (!string.IsNullOrEmpty(this.PlaceholderText))
            {
                SetPlaceHolder(true);
                this.Update();
            }
        }

        private void SetPlaceHolder(bool addEvents)
        {
            if (addEvents)
            {  
                this.LostFocus += txt_lostfocus;
                this.Click += txt_click;
            }

            this.Text = PlaceholderText;
            this.ForeColor = PlaceholderForeColor;
            this.Font = PlaceholderFont;
        }

        private void txt_click(object sender, EventArgs e)
        {
            // IsNotFirstClickOnThis:
            // if there is no other control in the form
            // we will have a problem after the first load
            // because we dont other focusable control to move the focus to
            // and we dont want to remove the place holder
            // only on first time the place holder will be removed by click event
            RemovePlaceHolder();
            this.GotFocus += txt_focus;
            // no need for this event listener now
            this.Click -= txt_click;
        }

        private void RemovePlaceHolder()
        {
            this.Text = "";
            this.ForeColor = TextForeColor;
            this.Font = TextFont;
        }
        private void txt_lostfocus(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.Text))
            {
                // set placeholder again
                SetPlaceHolder(false);
            }
        }

        private void txt_focus(object sender, EventArgs e)
        {
            if (this.Text == PlaceholderText)
            {
                // IsNotFirstClickOnThis:
                // if there is no other control in the form
                // we will have a problem after the first load
                // because we dont other focusable control to move the focus to
                // and we dont want to remove the place holder
                RemovePlaceHolder();
            }
        }
    }
}
jonathana
fuente
-1

Solución muy efectiva aquí para el control de WindowsForms TextBox. (No estoy seguro acerca de XAML).

Esto funcionará también en modo Multilínea.

Probablemente puede extenderse a otros controles, como el control ComboBox (no marcado)

Anton Norko
fuente
-1

Funciona de maravilla.

public class WTextBox : TextBox
{
    private string _placeholder;


    [Category("Appearance")]
    public string Placeholder
    {
        get { return _placeholder; }
        set
        {
            _placeholder = value ?? string.Empty;
            Invalidate();
        }
    }

    public WTextBox()
    {
        _placeholder = string.Empty;
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg != 0xF || Focused || !string.IsNullOrEmpty(Text) || string.IsNullOrWhiteSpace(_placeholder))
        {
            return;
        }

        using (var g = CreateGraphics())
        {
            TextRenderer.DrawText(g, _placeholder, Font, ClientRectangle, SystemColors.GrayText, BackColor, TextFormatFlags.Left);
        }
    }
}
Sergey
fuente
Agregue los usos necesarios
Akku