web-dev-qa-db-fra.com

Comment implémenter une zone de texte qui affiche "Tapez ici"?

Afficher " Tapez ici pour ... " jusqu'à ce que l'utilisateur entre du texte dans une TextBox est une fonctionnalité bien connue de l'utilisabilité. Comment implémenterait-on cette fonctionnalité en C #?

Mon idée est de remplacer OnTextChanged, mais la logique pour gérer les changements de texte de et vers " Tapez ici " est un peu délicate ...

Afficher " Tapez ici " lors de l’initialisation et le supprimer lors de la première saisie est facile, mais je souhaite afficher le message à chaque fois que le texte saisi est vide.

33
mafu

Vous recherchez une zone de texte avec "watermark"

Il existe un exemple d'implémentation pour C # ici

J'espère que ça aide

23
Marcos Placona

Quelque chose qui a fonctionné pour moi:

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

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

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

bool waterMarkActive est une variable membre de la classe et textBox est la TextBox. Cela devrait probablement être encapsulé cependant :) Il pourrait y avoir quelques problèmes avec cette approche, mais je ne suis au courant d'aucun.

J'ai récemment découvert que Windows prend en charge les marques d'eau dans les zones de texte. elles s'appellent des bannières de repère (voir ici ). C'est très facile à mettre en place:

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

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

textBox est une instance de TextBox, 0x1501 est le code du message Windows EM_SETCUEBANNER, la wParam peut être TRUE (différent de zéro) ou FALSE (zéro), et lParam est la marque d'eau que vous souhaitez afficher. wParam indique quand la bannière de cue doit être affichée; si elle est définie sur TRUE, la bannière de repère sera affichée même lorsque le contrôle est actif.

36
Pooven

Basé sur la réponse de @ Pooven (merci!), J'ai créé ce cours. Travaille pour moi.

/// <summary>
/// A textbox that supports a watermak hint.
/// </summary>
public class WatermarkTextBox : TextBox
{
    /// <summary>
    /// The text that will be presented as the watermak hint
    /// </summary>
    private string _watermarkText = "Type here";
    /// <summary>
    /// Gets or Sets the text that will be presented as the watermak hint
    /// </summary>
    public string WatermarkText
    {
        get { return _watermarkText; }
        set { _watermarkText = value; }
    }

    /// <summary>
    /// Whether watermark effect is enabled or not
    /// </summary>
    private bool _watermarkActive = true;
    /// <summary>
    /// Gets or Sets whether watermark effect is enabled or not
    /// </summary>
    public bool WatermarkActive
    {
        get { return _watermarkActive; }
        set { _watermarkActive = value; }
    }

    /// <summary>
    /// Create a new TextBox that supports watermak hint
    /// </summary>
    public WatermarkTextBox()
    {
        this._watermarkActive = true;
        this.Text = _watermarkText;
        this.ForeColor = Color.Gray;

        GotFocus += (source, e) =>
        {
            RemoveWatermak();
        };

        LostFocus += (source, e) =>
        {
            ApplyWatermark();
        };

    }

    /// <summary>
    /// Remove watermark from the textbox
    /// </summary>
    public void RemoveWatermak()
    {
        if (this._watermarkActive)
        {
            this._watermarkActive = false;
            this.Text = "";
            this.ForeColor = Color.Black;
        }
    }

    /// <summary>
    /// Applywatermak immediately
    /// </summary>
    public void ApplyWatermark()
    {
        if (!this._watermarkActive && string.IsNullOrEmpty(this.Text)
            || ForeColor == Color.Gray ) 
        {
            this._watermarkActive = true;
            this.Text = _watermarkText;
            this.ForeColor = Color.Gray;
        }
    }

    /// <summary>
    /// Apply watermak to the textbox. 
    /// </summary>
    /// <param name="newText">Text to apply</param>
    public void ApplyWatermark(string newText)
    {
        WatermarkText = newText;
        ApplyWatermark();
    }

}
8
Joel
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
  const int EM_SETCUEBANNER = 0x1501; 

  public Form1()
  {
      InitializeComponent();
      SendMessage(textBox1.Handle, EM_SETCUEBANNER, 1, "Username");
      SendMessage(textBox2.Handle, EM_SETCUEBANNER, 1, "Password");
  }
4

Je commence tout juste à apprendre le C # ce semestre, je ne suis donc pas un expert, mais cela a fonctionné pour moi:

private void Form1_Load(object sender, EventArgs e)
{
    textBox1.SelectionStart = 0;  //This keeps the text
    textBox1.SelectionLength = 0; //from being highlighted
    textBox1.ForeColor = Color.Gray;
}

private void textBox_MouseMove(object sender, MouseEventArgs e)
{
    Cursor.Current = Cursors.IBeam; //Without this the mouse pointer shows busy
}

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (textBox1.Text.Equals("Type here...") == true)
    {
        textBox1.Text = "";
        textBox1.ForeColor = Color.Black;
    }
}

private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
    if (textBox1.Text.Equals(null) == true || textBox1.Text.Equals("") == true)
    {
        textBox1.Text = "Type here...";
        textBox1.ForeColor = Color.Gray;
    }
}
3
Michael Raatz

Traitez l'événement de focus perdu et, si la propriété Text est vide, remplissez-le avec la chaîne par défaut.

1
Maurizio Reginelli

Si c'est ASP.NET (par opposition à winforms), vous pouvez faire ceci:

Si vous utilisez jQuery, ajoutez ceci à votre document prêt (ou quelle que soit votre initialisation de votre page):

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

Vous aurez besoin de faire un petit refactoring si vous sélectionnez plusieurs zones de texte (placez l'instruction if à l'intérieur d'un élément sur l'élément).

1
macca1

Dans la dernière version de C #, la zone de texte a la propriété Placeholder Text, qui fonctionne tout à fait. Il suffit donc de définir "Tapez ici ..." comme valeur de cette propriété.

1
LuisDeveloper

Basé sur la réponse de @ Joel. Je répare sa classe (merci pour la base!)

/// <summary>
/// A textbox that supports a watermak hint.
/// Based on: https://stackoverflow.com/a/15232752
/// </summary>
public class WatermarkTextBox : TextBox
{
    /// <summary>
    /// The text that will be presented as the watermak hint
    /// </summary>
    private string _watermarkText;

    /// <summary>
    /// Gets or Sets the text that will be presented as the watermak hint
    /// </summary>
    public string WatermarkText
    {
        get { return _watermarkText; }
        set { _watermarkText = value; }
    }

    /// <summary>
    /// Whether watermark effect is enabled or not
    /// </summary>
    private bool _watermarkActive;
    /// <summary>
    /// Gets or Sets whether watermark effect is enabled or not
    /// </summary>
    public bool WatermarkActive
    {
        get { return _watermarkActive; }
        set { _watermarkActive = value; }
    }

    /// <summary>
    /// Create a new TextBox that supports watermak hint
    /// </summary>
    public WatermarkTextBox()
    {
        this.WatermarkActive = _watermarkActive;
        this.Text = _watermarkText;
    }

    protected override void OnCreateControl()
    {
        base.OnCreateControl();
        if (this.WatermarkActive)
            CheckWatermark();
    }

    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        CheckWatermark();
    }

    protected override void OnLostFocus(EventArgs e)
    {
        base.OnLostFocus(e);
        CheckWatermark();
    }        

    public void CheckWatermark()
    {
        if ((this.WatermarkActive) && String.IsNullOrWhiteSpace(this.Text))
        {
            ForeColor = Color.Gray;
            this.Text = _watermarkText;
        }
        else if ((this.WatermarkActive) && (!String.IsNullOrWhiteSpace(this.Text)))
        {
            if (this.Text == _watermarkText)
                this.Text = "";
            ForeColor = Color.Black;
        }
        else
            ForeColor = Color.Black;
    }
}
0
K1988

Vous pouvez dessiner la chaîne "Tapez ici" dans l'arrière-plan de la zone de texte jusqu'à ce qu'elle soit vide

0
Nagg

Afficher "Tapez ici pour ..." jusqu'à ce que l'utilisateur entre du texte dans une zone de texte est une fonctionnalité bien connue de l'utilisabilité. Comment implémenterait-on cette fonctionnalité en C #?

  1. Définissez textbox.text comme "Tapez ici pour ..."

  2. créer un événement, par exemple box_click ()

  3. -> Mettez ce code dans votre méthode

    private void box_Click(object sender, EventArgs e)
    {
        Textbox b = (Textbox)sender;
        b.Text = null;
    }
    
  4. assignez maintenant cette méthode à l'événement "Enter" de votre champ de texte (peut-être un ou plusieurs)

0
Sutanu Nandigrami

Basé sur la réponse de Ahmed Soliman Flasha, utiliser la classe suivante:

public class TextBoxHint : TextBox
{
    string _hint;

    [Localizable(true)]
    public string Hint
    {
        get { return _hint; }
        set { _hint = value; OnHintChanged(); }
    }

    protected virtual void OnHintChanged()
    {
        SendMessage(this.Handle, EM_SETCUEBANNER, 1, _hint);
    }     

    const int EM_SETCUEBANNER = 0x1501;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
}
0
Tomas Kubes

Si c'est pour ASP.NET, vous pouvez essayer TextBoxWatermark .

S'il s'agit de Windows Forms, cela fait déjà l'objet d'une réponse ici dans SO.

0
Ashish Gupta

PRODUIT UNE SORTIE SIMILAIRE EN HTML WATERMARK

Voici mon code pour la zone de texte "filigrane" ou "aperçu" - fonctionne très bien! Utilisation de l'application Windows Forms.

NOTE: Cet exemple contient 3 zones de texte, chacune ayant la méthode ci-dessous pour l'événement "quitter la souris" et l'événement "entrer la souris", respectivement.

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

private void textBoxFav_Enter(object sender, EventArgs e) {
  TextBox textbox = (TextBox)sender;
  if (textbox.Text == "Favorite Food" || textbox.Text == "Favorite Drink" || textbox.Text == "Favorite Desert") {
    textbox.Text = "";
    textbox.ForeColor = Color.Black;
  }
}
0
Cordell

Pourquoi utiliser OnTextChanged? Je suggérerais de supprimer le texte "Tapez ici" lorsque la zone de texte est activée . Lorsque le contrôle perd le focus et qu'aucun texte n'est saisi, vous pouvez l'afficher à nouveau.

Même résultat et pas besoin de logique délicate.

0
lboshuizen