Dodanie tekstu zastępczego do pola tekstowego


147

Szukam sposobu, aby dodać tekst zastępczy do pola tekstowego, tak jak w przypadku pola tekstowego w html5.

To znaczy, jeśli pole tekstowe nie ma tekstu, to dodaje tekst Enter some text here, gdy użytkownik go kliknie, tekst zastępczy znika i umożliwia użytkownikowi wprowadzenie własnego tekstu, a jeśli pole tekstowe traci fokus i nadal nie ma tekstu, to symbol zastępczy jest dodane z powrotem do pola tekstowego.


4
Nie używaj właściwości Text dla tekstu zastępczego. Będzie kolidować z wiązaniem. Użyj AdornerDecorator ( msdn.microsoft.com/en-us/library/… )
Pavel Voronin


5
Tylko do Twojej wiadomości - znak wodny, czyli tekst podpowiedzi, czyli tekst zastępczy, czyli baner podpowiedzi . Wszystkie te terminy mają synonimiczny zamiar.
RBT

Odpowiedzi:


91

Czy nie byłoby to coś takiego:

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

To tylko pseudokod, ale koncepcja istnieje.


Dzięki. Spodziewałem się, że będzie jakiś kod XAML, którego można użyć do utworzenia symbolu zastępczego. Dziękuję za pomoc
Boardy

1
Miałem nadzieję, że uda mi się znaleźć rozwiązanie, które zachowa tekst zastępczy w polu tekstowym do czasu wprowadzenia tekstu przez użytkownika. Wydaje się, że to działałoby lepiej.
Użytkownicy DROP TABLE

6
To zadziała, ALE jeśli wartość pola tekstowego jest powiązana ze źródłem, prawdopodobnie masz problem.
Pavel Voronin

1
To dobre proste rozwiązanie, tyle tylko, że nawet po wpisaniu tekstu, jeśli użytkownik ponownie kliknie w pole tekstowe (np. Aby dodać więcej tekstu lub usunąć niektóre znaki), całe pole tekstowe straci wprowadzoną wartość
Bibaswann Bandyopadhyay

2
RemoveTexti AddTextmetoda powinna być public void, brakuje nieważne . Jak powiedział @BibaswannBandyopadhyay, RemoveTextmetoda może wyglądać następująco:if (myTxtbx.Text == "Enter text here...") {myTxtbx.Text = "";}
KaKa

91

Możesz tego użyć, działa dla mnie i jest niezwykle prostym rozwiązaniem.

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

Stosowanie:

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

Wcześniejsze


1
Cześć @MacGile, zmodyfikowałem Twoje świetne rozwiązanie, ponieważ potrzebuję dwukierunkowego wiązania między oryginalną właściwością tekstu a właściwością textSource.Text.
Gábor Plesz

1
@Rob umieścił go w słowniku zasobów. Window.Resources itp.
Brian

6
W przypadku problemów z koncentracją dodaj to: <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusManager.FocusedElement" TargetName="textSource" Value="{Binding RelativeSource={RelativeSource Self}}" /> </Trigger> </ControlTemplate.Triggers>
Cihan Yakar

1
Przykleiłbym TextWrapping="wrap"oba znaczniki TextBox w Style, na wypadek gdybyś chciał zrobić wieloliniowy TextBox z tekstem zastępczym, tak jak ja.
jpcguy89

1
@Sachin Poprawiłem właściwość MaxLenght. Problem polega na tym, że jedno pole tekstowe jest zastępowane dwoma polami tekstowymi. Jeden dla danych wejściowych i jeden dla symbolu zastępczego. Aby naprawić uszkodzony właściwości wystarczy dodać je do pierwszego pola tekstowego tak: <TextBox Text="{Binding Path=Text, RelativeSource=RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" MaxLength="{TemplateBinding MaxLength}" />. W twoim przypadku prawdopodobnie musisz dodaćAcceptsReturn="{TemplateBinding AcceptsReturn}"
ColmanJ

47

Zamiast obsługiwać zdarzenia wejścia i opuszczenia fokusa w celu ustawienia i usunięcia tekstu zastępczego, można użyć funkcji Windows SendMessage, aby wysłać EM_SETCUEBANNERwiadomość do naszego pola tekstowego, aby wykonać pracę za nas.

Można to zrobić w dwóch łatwych krokach. Najpierw musimy ujawnić funkcję Windows SendMessage.

private const int EM_SETCUEBANNER = 0x1501;

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

Następnie po prostu wywołaj metodę z uchwytem naszego pola tekstowego, wartością EM_SETCUEBANNER i tekstem, który chcemy ustawić.

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

Odniesienie: Ustaw tekst zastępczy dla pola tekstowego (tekst podpowiedzi)


10
Uwaga: to nie działa w przypadku WPF . Zobacz: stackoverflow.com/questions/5054872/…
ArtOfCode

Najlepsza odpowiedź tutaj, ale zauważ, że Form_Load jest za wcześnie, musiałem poczekać do Form_Shown, zanim zadziałało.
Jay Croghan

Jedyne, czego nienawidzę w tym, to to, że tekst znika, gdy tylko kontrolka stanie się fokusem, co oznacza, że ​​jeśli nie złapałeś tego, co powiedział (i jest to ważne), musisz go kliknąć, aby ponownie zobaczyć tekst zastępczy . Dodałem kolejną odpowiedź, aby dodać symbol zastępczy, który znika dopiero po rozpoczęciu pisania przez użytkownika.
Gabriel Luci

19

Dodaj tę klasę do swojego projektu i skompiluj swoje rozwiązanie. Kliknij, aby przejść do Toolbox w Visual Studio, zobaczysz nowy składnik Textbox o nazwie PlaceholderTextBox. Usuń swoje obecne pole tekstowe na designe formularza i zamień na PlaceHolderTextBox.

wprowadź opis obrazu tutaj

PlaceHolderTextBox ma właściwość PlaceHolderText. Ustaw dowolny tekst i miłego dnia :)

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
Gdy jakaś inna kontrolka działa na wartość Textwłaściwości (np. Pole tekstowe używane do filtrowania listy), do filtrowania zostanie użyty symbol zastępczy. Wartość zastępcza powinna być używana tylko do wyświetlania, dlatego Texttymczasowe zastępowanie właściwości nie jest dobrym pomysłem .
Roland Illig

1
Zgrabne rozwiązanie, podoba mi się. Dodałbym te zastosowania do klasy, aby działało: using System; using System.Drawing; using System.Windows.Forms;Dzięki za to!
Eldoïr

18

To nie jest mój kod, ale używam go dużo i działa idealnie ... TYLKO 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>

1
Działa jak urok, a jeśli dodasz wyzwalacz do IsFocused, zastępując DataTriggergo następującymi MultiDataTrigger, działa jeszcze lepiej, moim skromnym zdaniem:<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

Załączone nieruchomości na ratunek:

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

Stosowanie:

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

Dzięki za dostarczenie tego miłego rozwiązania. Jednak użycie twojego rozwiązania daje w wyniku a) czarny tekst zastępczy zamiast jasnoszarego orazb) nie wyświetla tekstu zastępczego po uruchomieniu aplikacji (ale po ustawieniu fokusu w innym miejscu). Czy mógłbyś poprawić swoją odpowiedź w tym względzie?
Yoda

1
@Yoda Jeśli udaje mi się nie zapomnieć, aż wrócę do domu i będzie patrzeć na jej poprawę, tak - dlaczego nie
Dbl

1
Naprawiono pusty symbol zastępczy do momentu ustawienia ostrości / rozogniskowania.
Siergiej

1
@Yoda Cześć, nie mam nic przeciwko, jeśli jest zrobione ostrożnie i niczego nie psuje.
Sergey

1
@Yoda, przepraszam, od jakiegoś czasu nie pracuję z WPF, w tej chwili nawet nie mam go zainstalowanego. Możesz dodać inną właściwość zależności o nazwie PlaceholderColorwith typeof(Brush). Następnie zmień textBox.Foregroundwłaściwość ShowPlaceholdermetody i przywróć ją z powrotem w HidePlaceholdermetodzie.
Siergiej

5

Chociaż używanie EM_SETCUEBANNERwiadomości jest prawdopodobnie najprostsze, nie podoba mi się to, że tekst zastępczy znika, gdy element sterujący staje się aktywny. To moje zwierzę irytacja, kiedy wypełniam formularze. Muszę go wyłączyć, aby zapamiętać, do czego służy to pole.

Oto kolejne rozwiązanie dla WinForms. Nakłada się Labelna element sterujący, który znika tylko wtedy, gdy użytkownik zacznie pisać.

Z pewnością nie jest kuloodporny. Akceptuje dowolne Control, ale testowałem tylko z rozszerzeniem TextBox. Może wymagać modyfikacji, aby działał z niektórymi kontrolkami. Metoda zwraca Labelkontrolę w przypadku, gdy trzeba ją nieco zmodyfikować w określonym przypadku, ale może to nigdy nie być potrzebne.

Użyj tego w ten sposób:

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

Oto metoda:

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

Na podstawie odpowiedzi ExceptionLimeCat, poprawa:

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

Oznaczałoby to, że masz przycisk, który umożliwia wykonanie akcji, na przykład zalogowanie się lub coś podobnego. Przed wykonaniem czynności sprawdzasz, czy pole tekstowe jest wypełnione. Jeśli nie, to zastąpi tekst

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

To trochę kiepskie, ale sprawdzanie tekstu pod kątem wartości, którą mu podajesz, jest najlepsze, co mogę zrobić, a nie za dobre w języku C #, aby uzyskać lepsze rozwiązanie.


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

Proszę wyjaśnić swoją odpowiedź, zamiast po prostu wrzucać do niej fragment kodu.
Załóż pozew Moniki

1

Wymyśliłem metodę, która działała dla mnie, ale tylko dlatego, że chciałem użyć nazwy pola tekstowego jako symbolu zastępczego. Zobacz poniżej.

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

Oto rozwiązanie zainspirowane @Kemal Karadag.

Zauważyłem, że każde zamieszczone tutaj rozwiązanie polega na skupieniu się,

Chociaż chciałem, aby mój symbol zastępczy był dokładnym klonem standardowego symbolu zastępczego HTML w Google Chrome.

Zamiast ukrywać / pokazywać symbol zastępczy, gdy pole jest skupione,

Ukrywam / pokazuję symbol zastępczy w zależności od długości tekstu pola:

Jeśli pole jest puste, wyświetlany jest symbol zastępczy, a jeśli wpiszesz w polu, symbol zastępczy zniknie.

Ponieważ jest dziedziczony ze standardowego TextBox, możesz go znaleźć w swoim 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

Wypróbuj następujący kod:

<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

możesz to również zrobić po kliknięciu myszą, załóżmy, że Twój tekst zastępczy to „nazwa_użytkownika”

 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
Pytanie już rozwiązane, po co wartość dodana tej odpowiedzi? Nie ma żadnego wyjaśnienia, dodaj wszystko, spróbuj to wyjaśnić.
Jannik

0

Zamiast używać właściwości .Text obiektu TextBox, nałożyłem TextBlock na symbol zastępczy. Nie mogłem użyć właściwości .Text, ponieważ została ona powiązana ze zdarzeniem.

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

Wynik: wprowadź opis obrazu tutaj


0

Możesz też spróbować w ten sposób.

wywołać funkcję

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

napisz tę funkcję

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

są LEPSZE rozwiązania, ale najłatwiejsze rozwiązanie jest tutaj: ustaw tekst pola tekstowego na żądany ciąg, a następnie utwórz funkcję, która usuwa tekst, uruchom tę funkcję w polu tekstowym Focus Enter event


0

Napisałem niestandardową kontrolkę wielokrotnego użytku, być może może pomóc komuś, kto musi zaimplementować wiele zastępczych pól tekstowych w swoim projekcie.
oto klasa niestandardowa z przykładem implementacji instancji, którą można łatwo przetestować, wklejając ten kod w nowym projekcie winForms przy użyciu 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

Bardzo skutecznym rozwiązaniem tutaj o kontrolę WindowsForms tekstowym. (nie mam pewności co do XAML).

Działa to również w trybie Multliline.

Prawdopodobnie można go rozszerzyć o inne kontrolki, takie jak kontrolka ComboBox (niezaznaczona)


-1

Działa jak marzenie.

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

Dodaj niezbędne zastosowania
Akku,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.