Ajout de texte d'espace réservé à la zone de texte


147

Je cherche un moyen d'ajouter du texte d'espace réservé à une zone de texte comme vous le pouvez avec une zone de texte en html5.

C'est-à-dire que si la zone de texte n'a pas de texte, elle ajoute le texte Enter some text here, lorsque l'utilisateur clique dessus, le texte de l'espace réservé disparaît et permet à l'utilisateur d'entrer son propre texte, et si la zone de texte perd le focus et qu'il n'y a toujours pas de texte, l'espace réservé est ajouté à la zone de texte.


4
N'utilisez pas la propriété Text pour le texte d'espace réservé. Cela interférera avec la liaison. Utiliser AdornerDecorator ( msdn.microsoft.com/en-us/library/… )
Pavel Voronin


5
Juste un FYI - Watermark aka texte d'indication aka texte d'espace réservé aka bannière de repère . Tous ces termes ont également une intention.
RBT

Réponses:


91

Ne serait-ce pas quelque chose comme ça:

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

C'est juste un pseudo-code mais le concept est là.


Merci, je m'attendais à ce qu'il y ait une sorte de XAML qui puisse être utilisé pour créer l'espace réservé. Merci pour votre aide
Boardy

1
J'espérais trouver une solution qui conserverait le texte de l'espace réservé dans la zone de texte jusqu'à ce que l'utilisateur entre le texte. Il semble que cela fonctionnerait mieux.
Utilisateurs de DROP TABLE

6
Cela fonctionnera MAIS si la valeur de la zone de texte est liée à la source, vous avez probablement un problème.
Pavel Voronin

1
C'est une bonne solution simple, la seule chose est que même après la saisie de texte, si l'utilisateur clique à nouveau sur la zone de texte (par exemple pour ajouter plus de texte ou supprimer des caractères), toute la zone de texte perdra la valeur saisie
Bibaswann Bandyopadhyay

2
RemoveTextet la AddTextméthode devrait être public void, vide manquant . Et comme @BibaswannBandyopadhyay l'a dit, la RemoveTextméthode pourrait être la suivante:if (myTxtbx.Text == "Enter text here...") {myTxtbx.Text = "";}
KaKa

91

Vous pouvez l'utiliser, cela fonctionne pour moi et c'est une solution extrêmement 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>

Usage:

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

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


1
Salut @MacGile, j'ai modifié votre excellente solution, car j'ai besoin de la liaison bidirectionnelle entre la propriété text originale et la propriété textSource.Text.
Gábor Plesz

1
@Rob l'a mis dans un dictionnaire de ressources. Window.Resources, etc.
Brian

6
Pour les problèmes de focus, ajoutez ceci: <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusManager.FocusedElement" TargetName="textSource" Value="{Binding RelativeSource={RelativeSource Self}}" /> </Trigger> </ControlTemplate.Triggers>
Cihan Yakar

1
Je clouerais TextWrapping="wrap"sur les deux balises TextBox dans le style, au cas où vous voudriez faire une TextBox multiligne avec du texte d'espace réservé comme je l'ai fait.
jpcguy89

1
@Sachin J'ai corrigé ma propriété MaxLenght. Le problème est qu'une zone de texte est remplacée par 2 zones de texte. Un pour l'entrée et un pour l'espace réservé. Pour les propriétés de fix cassé il vous suffit de les ajouter à la première zone de texte comme celui - ci: <TextBox Text="{Binding Path=Text, RelativeSource=RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" MaxLength="{TemplateBinding MaxLength}" />. Dans votre cas, vous devez probablement ajouterAcceptsReturn="{TemplateBinding AcceptsReturn}"
ColmanJ

47

Au lieu de gérer les événements d'entrée et de sortie de focus afin de définir et de supprimer le texte de l'espace réservé, il est possible d'utiliser la fonction Windows SendMessage pour envoyer un EM_SETCUEBANNERmessage à notre zone de texte afin de faire le travail à notre place.

Cela peut être fait en deux étapes faciles. Nous devons d'abord exposer la SendMessagefonction 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);

Ensuite, appelez simplement la méthode avec le handle de notre zone de texte, la valeur de EM_SETCUEBANNER et le texte que nous voulons définir.

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

Référence: définir le texte de l'espace réservé pour la zone de texte (texte de repère)


10
Remarque: cela ne fonctionne pas pour WPF . Voir: stackoverflow.com/questions/5054872/…
ArtOfCode

Meilleure réponse ici, mais notez que Form_Load est trop tôt, j'ai dû attendre Form_Shown avant que cela fonctionne.
Jay Croghan

La seule chose que je déteste à ce sujet est que le texte disparaît dès que le contrôle obtient le focus, ce qui signifie que si vous n'avez pas compris ce qu'il a dit (et c'est important), vous devez cliquer dessus pour voir à nouveau le texte de l'espace réservé . J'ai ajouté une autre réponse pour ajouter un espace réservé qui ne disparaît qu'après que l'utilisateur commence à taper.
Gabriel Luci

19

Ajoutez cette classe à votre projet et créez votre solution. Cliquez sur Toolbox sur Visual Studio, vous verrez un nouveau composant de zone de texte nommé PlaceholderTextBox. Supprimez votre zone de texte actuelle sur la conception du formulaire et remplacez-la par PlaceHolderTextBox.

entrez la description de l'image ici

PlaceHolderTextBox a une propriété PlaceHolderText. Définissez le texte que vous voulez et passez une bonne journée :)

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

11
Lorsqu'un autre contrôle agit sur la valeur de la Textpropriété (par exemple une zone de texte utilisée pour filtrer une liste), l'espace réservé sera utilisé pour le filtrage. La valeur d'espace réservé ne doit être utilisée que pour l'affichage, il n'est donc pas judicieux de remplacer Texttemporairement la propriété.
Roland Illig

1
Solution soignée, j'aime ça. J'ajouterais ces utilisations en plus de la classe, afin que cela fonctionne: using System; using System.Drawing; using System.Windows.Forms;Merci pour cela!
Eldoïr

18

Ce n'est pas mon code, mais je l'utilise beaucoup et cela fonctionne parfaitement ... XAML UNIQUEMENT

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

1
Fonctionne comme un charme, et si vous ajoutez un déclencheur à IsFocused en remplaçant le DataTriggerpar le suivant MultiDataTrigger, cela fonctionne encore mieux à mon humble avis:<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

Propriétés attachées à la rescousse:

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

Usage:

<TextBox Text="hi" local:TextboxExtensions.Placeholder="Hello there"></TextBox>

Merci d'avoir fourni cette belle solution. Cependant, en utilisant votre solution, il en résulte a) un texte d'espace réservé noir au lieu d'un texte gris clair et b) aucun texte d'espace réservé au démarrage de l'application (mais après la mise au point, puis la mise en évidence ailleurs). Pourriez-vous améliorer votre réponse à cet égard?
Yoda le

1
@Yoda Si je parviens à ne pas l'oublier jusqu'à ce que je rentre à la maison, je chercherai à l'améliorer, ouais - pourquoi pas
Dbl

1
Espace réservé vide jusqu'à ce que la mise au point / la déconcentration soit corrigée.
Sergey

1
@Yoda Salut, ça ne me dérange pas si c'est fait avec soin et ne casse rien.
Sergey le

1
@Yoda, désolé, je ne travaille pas avec WPF depuis un moment, je ne l'ai même pas installé pour le moment. Vous pouvez ajouter une autre propriété de dépendance nommée PlaceholderColoravec typeof(Brush). Modifiez ensuite la textBox.Foregroundpropriété de la ShowPlaceholderméthode et restaurez-la dans la HidePlaceholderméthode.
Sergey le

5

Lors de l'utilisation du EM_SETCUEBANNER message soit probablement la plus simple, une chose que je n'aime pas est que le texte d'espace réservé disparaît lorsque le contrôle obtient le focus. C'est une bête noire à moi quand je remplis des formulaires. Je dois cliquer dessus pour me souvenir à quoi sert le champ.

Voici donc une autre solution pour WinForms. Il superpose un Labelau-dessus du contrôle, qui disparaît uniquement lorsque l'utilisateur commence à taper.

Ce n'est certainement pas à l'épreuve des balles. Il en accepte tous Control, mais je n'ai testé qu'avec un TextBox. Il peut avoir besoin de modifications pour fonctionner avec certains contrôles. La méthode retourne le Labelcontrôle au cas où vous auriez besoin de le modifier un peu dans un cas spécifique, mais cela peut ne jamais être nécessaire.

Utilisez-le comme ceci:

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

Voici la méthode:

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

4

Sur la base de la réponse d'ExceptionLimeCat, une amélioration:

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


3

Cela signifierait que vous avez un bouton qui vous permet de faire une action, comme la connexion ou quelque chose. Avant de faire l'action, vérifiez si la zone de texte est remplie. Sinon, elle remplacera le texte

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

C'est un peu ringard, mais vérifier le texte pour la valeur que vous lui donnez est le mieux que je puisse faire atm, pas si bon en c # pour obtenir une meilleure solution.


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

Veuillez expliquer votre réponse au lieu de simplement jeter un tas de code dans votre réponse.
Fund Monica's Lawsuit

1

J'ai proposé une méthode qui a fonctionné pour moi, mais uniquement parce que j'étais prêt à utiliser le nom de la zone de texte comme espace réservé. Voir ci-dessous.

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

1

Ici, je viens avec cette solution inspirée de @Kemal Karadag.

J'ai remarqué que chaque solution publiée ici repose sur l'objectif,

Alors que je voulais que mon espace réservé soit le clone exact d'un espace réservé HTML standard dans Google Chrome.

Au lieu de masquer / afficher l'espace réservé lorsque la zone est focalisée,

Je masque / affiche l'espace réservé en fonction de la longueur du texte de la boîte:

Si la zone est vide, l'espace réservé est affiché et si vous tapez dans la zone, l'espace réservé disparaît.

Comme il est hérité d'une TextBox standard, vous pouvez le trouver dans votre Toolbox!

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

0

Essayez le code suivant:

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


0

vous pouvez également le faire lorsque la souris clique, supposons que votre texte d'espace réservé soit "User_Name"

 private void textBox1_MouseClick(object sender, MouseEventArgs e)
 {
     if(textBox1.Text == "User_Name")
          textBox1.Text = "";
 }

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

5
La question est déjà résolue, quelle est la valeur ajoutée de cette réponse? Il n'y a pas d'explication, ajoutez tout, essayez de l'expliquer.
Jannik

0

Au lieu d'utiliser la propriété .Text d'un TextBox, j'ai superposé un TextBlock avec l'espace réservé. Je n'ai pas pu utiliser la propriété .Text car elle était liée à un événement.

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

Résultat: entrez la description de l'image ici


0

Vous pouvez également essayer de cette manière.

appeler la fonction

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

écrivez cette fonction

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

        };
}

0

il existe de MEILLEURES solutions, mais la solution la plus simple est ici: définissez le texte de la zone de texte sur la chaîne souhaitée, puis créez une fonction qui supprime le texte, activez cette fonction sur la zone de texte Focus Enter event


0

J'ai écrit un contrôle personnalisé réutilisable, peut-être qu'il peut aider quelqu'un qui a besoin d'implémenter plusieurs zones de texte d'espace réservé dans son projet.
voici la classe personnalisée avec exemple d'implémentation d'une instance, vous pouvez tester facilement en collant ce code sur un nouveau projet winforms en utilisant 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();
            }
        }
    }
}

-1

Solution très efficace ici pour le contrôle TextBox de WindowsForms. (pas sûr de XAML).

Cela fonctionnera également en mode multiligne.

Il peut probablement être étendu pour d'autres contrôles, comme le contrôle ComboBox (non coché)


-1

Fonctionne comme un charme.

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

Veuillez ajouter les utilisations nécessaires
Akku
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.