Adicionando texto de espaço reservado à caixa de texto

147

Estou procurando uma maneira de adicionar texto de espaço reservado a uma caixa de texto como você pode com uma caixa de texto em html5.

Ou seja, se a caixa de texto não tiver texto, ele será adicionado Enter some text here; quando o usuário clicar nela, o texto do espaço reservado desaparecerá e permitirá que o usuário insira seu próprio texto; se a caixa de texto perder o foco e ainda não houver texto, o espaço reservado será adicionado de volta à caixa de texto.

Boardy
fonte
4
Não use a propriedade Text para o texto do espaço reservado. Isso interferirá na ligação. Use AdornerDecorator ( msdn.microsoft.com/en-us/library/… )
Pavel Voronin
2
Dê uma olhada em stackoverflow.com/questions/833943/…
SepehrM 8/08
5
Apenas um FYI - Marca d'água, também conhecido como texto de dica, também conhecido como texto de espaço reservado, conhecido como banner de sugestão . Todos esses termos têm intenção sinônima.
RBT

Respostas:

91

Não seria algo assim:

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

Isso é apenas pseudocódigo, mas o conceito está lá.

ExceptionLimeCat
fonte
Obrigado, eu esperava que houvesse algum tipo de XAML que pudesse ser usado para criar o espaço reservado. Obrigado pela sua ajuda.
Boardy
1
Esperava encontrar uma solução que mantivesse o texto do espaço reservado na caixa de texto até o usuário digitar o texto. Parece que isso funcionaria melhor.
usuários DROP TABLE
6
Isso funcionará, mas se o valor da caixa de texto estiver vinculado à origem, você provavelmente terá um problema.
Pavel Voronin 14/03
1
Este é boa solução simples, a única coisa é que, mesmo após a introdução de texto, se o usuário clica novamente na caixa de texto (por exemplo, para acrescentar mais texto ou excluir alguns caracteres) de toda a caixa de texto perderá o valor inserido
Bibaswann Bandyopadhyay
2
RemoveTexte AddTextmétodo deve ser public void, ausente nulo . E como @BibaswannBandyopadhyay disse, o RemoveTextmétodo poderia ser esta:if (myTxtbx.Text == "Enter text here...") {myTxtbx.Text = "";}
KaKa
91

Você pode usar isso, está funcionando para mim e é uma solução extremamente simples.

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

O que outras pessoas estão dizendo

MacGile
fonte
1
Oi @ MacGile, eu modifiquei sua ótima solução, porque eu preciso da ligação bidirecional entre a propriedade de texto original e a propriedade textSource.Text.
Gábor Plesz
1
@ Rob colocá-lo em um dicionário de recursos. Window.Resources, etc.
Brian
6
Para questões de foco, adicione este: <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusManager.FocusedElement" TargetName="textSource" Value="{Binding RelativeSource={RelativeSource Self}}" /> </Trigger> </ControlTemplate.Triggers>
Cihan Yakar
1
Eu aderiria a TextWrapping="wrap"ambas as tags TextBox no Style, caso você queira criar uma TextBox com várias linhas com texto Placeholder como eu.
precisa saber é o seguinte
1
@Sachin Corrigi minha propriedade MaxLenght. O problema é que uma caixa de texto é substituída por 2 caixas de texto. Um para entrada e outro para o espaço reservado. Para propriedades de correção quebrado você só precisa adicioná-los à primeira caixa de texto como este: <TextBox Text="{Binding Path=Text, RelativeSource=RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" MaxLength="{TemplateBinding MaxLength}" />. No seu caso, você provavelmente precisará adicionarAcceptsReturn="{TemplateBinding AcceptsReturn}"
ColmanJ
47

Em vez de manipular os eventos de entrada e saída de foco para definir e remover o texto do espaço reservado, é possível usar a função SendMessage do Windows para enviar EM_SETCUEBANNERmensagem para a nossa caixa de texto para fazer o trabalho por nós.

Isso pode ser feito com duas etapas fáceis. Primeiro, precisamos expor a SendMessagefunção do 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);

Em seguida, basta chamar o método com o identificador de nossa caixa de texto, o valor de EM_SETCUEBANNER e o texto que queremos definir.

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

Referência: definir texto de espaço reservado para caixa de texto (texto de sugestão)

Abdullah Qudeer
fonte
10
Nota: isso não funciona para o WPF . Veja: stackoverflow.com/questions/5054872/…
ArtOfCode
Melhor resposta aqui, mas observe que Form_Load é muito cedo, tive que esperar até Form_Shown antes de funcionar.
Jay Croghan
A única coisa que eu odeio é que o texto desaparece assim que o controle fica em foco, o que significa que se você não captou o que disse (e é importante), é necessário clicar nele para ver o texto do espaço reservado novamente . Adicionei outra resposta para adicionar um espaço reservado que desaparece somente depois que o usuário começa a digitar.
Gabriel Luci 12/12
19

Adicione essa classe ao seu projeto e construa sua solução. Clique na caixa de ferramentas no visual studio e você verá um novo componente da caixa de texto chamado PlaceholderTextBox. Exclua sua caixa de texto atual no formulário de designe e substitua por PlaceHolderTextBox.

insira a descrição da imagem aqui

PlaceHolderTextBox tem uma propriedade PlaceHolderText. Defina qualquer texto que desejar e tenha um bom dia :)

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
fonte
11
Quando algum outro controle atua sobre o valor da Textpropriedade (por exemplo, uma caixa de texto usada para filtrar uma lista), o espaço reservado será usado para filtrar. O valor do espaço reservado deve ser usado apenas para exibição, portanto, não é uma boa ideia substituir a Textpropriedade temporariamente.
Roland Illig 27/08/16
1
Solução pura, eu gosto. Eu adicionaria esses usos no topo da classe, para fazê-lo funcionar: using System; using System.Drawing; using System.Windows.Forms;Obrigado por isso!
Eldoïr
18

Este não é o meu código, mas eu o uso muito e funciona perfeitamente ... SOMENTE 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
fonte
1
Funciona como um encanto e, se você adicionar um gatilho ao IsFocused, substituindo DataTriggero seguinte pelo seguinte MultiDataTrigger, ele funcionará ainda melhor na minha humilde opinião:<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

Propriedades anexadas ao resgate:

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
fonte
Obrigado por fornecer esta ótima solução. No entanto, usando sua solução, resulta em a) texto de espaço reservado preto em vez de cinza claro eb) não mostra texto de espaço reservado no início do aplicativo (mas depois de focar e depois definir o foco em outro lugar). Você se importaria de melhorar sua resposta a esse respeito?
Yoda
1
@Yoda Se eu conseguir não esquecê-lo até chegar em casa, vou tentar melhorá-lo, sim - por que não?
Dbl
1
Espaço reservado em branco até que o foco / desfoque seja fixo.
Sergey
1
@Yoda Oi, não me importo se for feito com cuidado e não quebrar nada.
Sergey
1
@ Yoda, desculpe, eu não trabalho com o WPF há um tempo, nem o tenho instalado no momento. Você pode adicionar outra propriedade de dependência nomeada PlaceholderColorcom typeof(Brush). Em seguida, altere a textBox.Foregroundpropriedade no ShowPlaceholdermétodo e restaure-a novamente no HidePlaceholdermétodo.
Sergey
5

Embora o uso da EM_SETCUEBANNERmensagem seja provavelmente mais simples, uma coisa de que não gosto é que o texto do espaço reservado desaparece quando o controle fica em foco. É uma irritação minha quando estou preenchendo formulários. Preciso clicar nele para lembrar para que serve o campo.

Então, aqui está outra solução para o WinForms. Sobrepõe um Labelno topo do controle, que desaparece apenas quando o usuário começa a digitar.

Certamente não é à prova de balas. Ele aceita qualquer Control, mas eu só testei com a TextBox. Pode ser necessário modificar para trabalhar com alguns controles. O método retorna o Labelcontrole caso você precise modificá-lo um pouco em um caso específico, mas isso pode nunca ser necessário.

Use-o assim:

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

Aqui está o 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
fonte
4

Com base na resposta de ExceptionLimeCat, uma melhoria:

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

Você pode obter o padrãoTemplate , modificá-lo sobrepondo ae TextBlockusar a Stylepara adicionar gatilhos que ocultam e mostram nos estados certos.

HB
fonte
3

Isso significa que você tem um botão que permite executar uma ação, como fazer login ou algo assim. Antes de executar a ação, verifique se a caixa de texto está preenchida. Caso contrário, ela substituirá o 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 = "";
     }
 }

É meio extravagante, mas verificar o texto quanto ao valor que você está dando é o melhor que posso fazer em atm, não tão bom em c # para obter uma solução melhor.

VJamie
fonte
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
fonte
Explique sua resposta em vez de apenas despejar um monte de código em sua resposta.
Fund Monica's Lawsuit
1

Eu vim com um método que funcionou para mim, mas apenas porque estava disposto a usar o nome da caixa de texto como meu espaço reservado. Ver abaixo.

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

Aqui eu venho com esta solução inspirada em @Kemal Karadag.

Percebi que todas as soluções postadas aqui dependem do foco,

Embora eu desejasse que meu espaço reservado fosse o clone exato de um espaço reservado HTML padrão no Google Chrome.

Em vez de ocultar / mostrar o espaço reservado quando a caixa estiver focada,

Eu oculto / mostro o espaço reservado, dependendo do tamanho do texto da caixa:

Se a caixa estiver vazia, o espaço reservado será mostrado e, se você digitar na caixa, o espaço reservado desaparecerá.

Como é herdado de um TextBox padrão, você pode encontrá-lo na sua Caixa de Ferramentas!

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();
        }
    }
}
Eldoïr
fonte
0

Tente o seguinte 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
fonte
0

txtUsuario.Attributes.Add ("marcador de posição", "Texto");

Everton Luke
fonte
0

você também pode fazer isso quando o mouse clicar, vamos supor que o texto do espaço reservado seja "Nome_do_Usuário"

 private void textBox1_MouseClick(object sender, MouseEventArgs e)
 {
     if(textBox1.Text == "User_Name")
          textBox1.Text = "";
 }
Adiii
fonte
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
fonte
5
A questão já está resolvida, o que está usando o valor agregado desta resposta? Não há explicação, adicione tudo, tente explicar.
Jannik
0

Em vez de usar a propriedade .Text de um TextBox, sobreponha um TextBlock com o espaço reservado. Não pude usar a propriedade .Text porque isso estava vinculado a um 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: insira a descrição da imagem aqui

andy
fonte
0

Você também pode tentar dessa maneira ..

chame a função

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

escreva esta função

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

existem soluções MELHORES, mas a solução mais fácil está aqui: defina o texto da caixa de texto com a string desejada e crie uma função que exclua o texto, faça com que essa função seja acionada na caixa de texto Evento Focus Enter

Jared
fonte
0

Eu escrevi um controle personalizado reutilizável, talvez possa ajudar alguém que precise implementar várias caixas de texto de espaço reservado em seu projeto.
aqui está a classe personalizada com exemplo de implementação de uma instância, você pode testar facilmente colando esse código em um novo projeto winforms usando o 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
fonte
-1

Solução muito eficaz aqui para o controle WindowsForms TextBox. (não tenho certeza sobre XAML).

Isso funcionará também no modo Multilinha.

Provavelmente pode ser estendido para outros controles, como o controle ComboBox (não marcado)

Anton Norko
fonte
-1

Funciona como um encanto.

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
fonte
Por favor, adicione os usos necessários
Akku