Добавление текста-заполнителя в текстовое поле

147

Я ищу способ добавить заполнитель текста в текстовое поле, как вы можете с помощью текстового поля в HTML5.

Т.е. если в текстовом поле нет текста, то он добавляет текст Enter some text here, когда пользователь нажимает на него, текст заполнителя исчезает и позволяет пользователю вводить свой собственный текст, а если текстовое поле теряет фокус, а текст все еще отсутствует, тогда заполнитель добавлен обратно в текстовое поле.

Boardy
источник
4
Не используйте свойство Text для текста-заполнителя. Это будет мешать закреплению. Используйте AdornerDecorator ( msdn.microsoft.com/en-us/library/… )
Павел Воронин,
2
Взгляните на stackoverflow.com/questions/833943/…
SepehrM
5
Просто FYI - Водяной знак, он же текст подсказки, он же текст заполнителя, он же баннер . Все эти термины имеют синонимное намерение.
RBT

Ответы:

91

Разве это не было бы что-то вроде этого:

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

Это просто псевдокод, но концепция есть.

ExceptionLimeCat
источник
Спасибо, я ожидал, что будет какой-то XAML, который можно использовать для создания заполнителя. Спасибо за вашу помощь
Boardy
1
Я надеялся найти решение, которое сохраняло бы текст заполнителя в текстовом поле, пока пользователь не введет текст. Похоже, это будет работать лучше.
DROP TABLE пользователи
6
Это будет работать НО, если значение текстового поля привязано к источнику, то у вас, вероятно, есть проблема.
Павел Воронин
1
Это хорошее простое решение, единственное, что даже после ввода текста, если пользователь снова нажимает на текстовое поле (например, чтобы добавить текст или удалить некоторые символы), все текстовое поле потеряет введенное значение
Bibaswann Bandyopadhyay
2
RemoveTextи AddTextметод должен быть public void, пропуская пустоту . И, как сказал @BibaswannBandyopadhyay, RemoveTextметод может быть таким:if (myTxtbx.Text == "Enter text here...") {myTxtbx.Text = "";}
КаКа
91

Вы можете использовать это, это работает для меня и является чрезвычайно простым решением.

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

Использование:

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

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

MacGile
источник
1
Привет @MacGile, я изменил твое отличное решение, потому что мне нужно двухстороннее связывание между исходным текстовым свойством и свойством textSource.Text.
Габор Плес
1
@Rob поместил его в словарь ресурсов. Окно. Ресурсы и т. Д.
Брайан
6
Для проблем фокуса добавьте это: <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="FocusManager.FocusedElement" TargetName="textSource" Value="{Binding RelativeSource={RelativeSource Self}}" /> </Trigger> </ControlTemplate.Triggers>
Cihan Yakar
1
Я бы добавил TextWrapping="wrap"оба тега TextBox в Style, если вы хотите создать многострочный TextBox с текстом Placeholder, как я.
jpcguy89
1
@Sachin Я исправил свой параметр MaxLenght. Проблема в том, что одно текстовое поле заменяется двумя текстовыми полями. Один для ввода и один для заполнителя. Чтобы исправить битые свойств нужно просто добавить их в первое текстовое поле , как это: <TextBox Text="{Binding Path=Text, RelativeSource=RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="textSource" Background="Transparent" Panel.ZIndex="2" MaxLength="{TemplateBinding MaxLength}" />. В вашем случае вам, вероятно, нужно добавитьAcceptsReturn="{TemplateBinding AcceptsReturn}"
ColmanJ
47

Вместо того чтобы обрабатывать события ввода и фокусировки фокуса, чтобы установить и удалить текст-заполнитель, можно использовать функцию Windows SendMessage, чтобы отправить EM_SETCUEBANNERсообщение в наше текстовое поле, чтобы выполнить работу за нас.

Это можно сделать с помощью двух простых шагов. Для начала нам нужно раскрыть SendMessageфункцию 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_SETCUEBANNER и текстом, который мы хотим установить.

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

Ссылка: Установить заполнитель текста для текстового поля (текст подсказки)

Абдулла Кудир
источник
10
Примечание: это не работает для WPF . См .: stackoverflow.com/questions/5054872/…
ArtOfCode
Лучший ответ здесь, но обратите внимание, что Form_Load слишком рано, мне пришлось ждать, пока Form_Shown, прежде чем он заработал.
Джей Кроган
Единственное, что я ненавижу в этом, это то, что текст исчезает, как только элемент управления получает фокус, а это означает, что если вы не уловили то, что он сказал (и это важно), вы должны нажать на него, чтобы снова увидеть текст заполнителя , Я добавил еще один ответ, чтобы добавить заполнитель, который исчезает только после того, как пользователь начинает печатать.
Габриэль Люси
19

Добавьте этот класс в ваш проект и постройте свое решение. Нажмите на Toolbox в Visual Studio, вы увидите новый компонент текстового поля с именем PlaceholderTextBox. Удалите текущее текстовое поле в форме дизайна и замените PlaceHolderTextBox.

введите описание изображения здесь

PlaceHolderTextBox имеет свойство PlaceHolderText. Установите любой текст, который вы хотите, и хорошего дня :)

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
Когда какой-либо другой элемент управления воздействует на значение Textсвойства (например, текстовое поле, используемое для фильтрации списка), заполнитель будет использоваться для фильтрации. Значение заполнителя следует использовать только для отображения, поэтому не рекомендуется Textвременно заменять свойство.
Роланд Иллиг
1
Оптимальное решение, мне это нравится. Я хотел бы добавить это использование в верхней части класса, чтобы заставить его работать: using System; using System.Drawing; using System.Windows.Forms;Спасибо за это!
Eldoïr
18

Это не мой код, но я часто его использую, и он отлично работает ... ТОЛЬКО 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
Работает как талисман, и если вы добавите триггер в IsFocused, заменив DataTriggerего следующим MultiDataTrigger, по моему скромному мнению, он будет работать еще лучше:<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

Прилагаемые свойства к спасению:

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

Использование:

<TextBox Text="hi" local:TextboxExtensions.Placeholder="Hello there"></TextBox>
дублированный
источник
Спасибо за предоставление этого хорошего решения. Однако, используя ваше решение, вы получите а) черный текст-заполнитель вместо светло-серого и б) не показывать текст-заполнитель при запуске приложения (но после фокусировки и затем установки фокуса в другом месте). Не могли бы вы улучшить свой ответ в этом отношении?
Йода
1
@Yoda Если мне удастся не забыть об этом, пока я не вернусь домой, я постараюсь улучшить его, да - почему бы и нет
Dbl
1
Пустой заполнитель, пока фокусировка / расфокусировка не исправлены.
Сергей
1
@Yoda Привет, я не против, если все сделано аккуратно и ничего не сломает.
Сергей
1
@Yoda, извини, я давно не работал с WPF, сейчас у меня даже не установлено. Вы можете добавить другое свойство зависимости PlaceholderColorс именем typeof(Brush). Затем измените textBox.Foregroundсвойство в ShowPlaceholderметоде и восстановите его обратно в HidePlaceholderметоде.
Сергей
5

Хотя использование EM_SETCUEBANNERсообщения, вероятно, самое простое, мне не нравится то, что текст-заполнитель исчезает, когда элемент управления получает фокус. Это моя любимая мозоль, когда я заполняю формы. Я должен нажать на нее, чтобы вспомнить, для чего это поле.

Итак, вот еще одно решение для WinForms. Он перекрывает Labelверхнюю часть элемента управления, которая исчезает только тогда, когда пользователь начинает печатать.

Это, конечно, не пуленепробиваемый. Он принимает любые Control, но я проверял только с TextBox. Может потребоваться модификация для работы с некоторыми элементами управления. Метод возвращает Labelэлемент управления в случае, если вам нужно немного изменить его в конкретном случае, но это может никогда не понадобиться.

Используйте это так:

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

Вот метод:

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

На основании ответа ExceptionLimeCat, улучшение:

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

Это будет означать, что у вас есть кнопка, которая позволяет вам выполнять действия, такие как вход в систему или что-то еще. Перед тем, как выполнить действие, вы проверяете, заполнено ли текстовое поле. Если нет, оно заменит текст.

 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 #, чтобы найти лучшее решение.

VJamie
источник
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"/>
Саиф Миф
источник
Пожалуйста, объясните свой ответ, а не просто добавьте в свой код кучу кода.
Фонд Моника иск
1

Я придумал метод, который работал для меня, но только потому, что я хотел использовать имя текстового поля в качестве заполнителя. Увидеть ниже.

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
источник
1

Вот и я с этим решением, вдохновленным @Kemal Karadag.

Я заметил, что каждое решение, опубликованное здесь, опирается на фокус,

Хотя я хотел, чтобы мой заполнитель был точным клоном стандартного заполнителя HTML в Google Chrome.

Вместо того, чтобы скрывать / показывать заполнитель, когда окно сфокусировано,

Я скрываю / показываю заполнитель в зависимости от длины текста поля:

Если поле пусто, отображается местозаполнитель, а при вводе в поле заполнитель исчезает.

Так как он унаследован от стандартного TextBox, вы можете найти его в вашей панели инструментов!

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
источник
0

Попробуйте следующий код:

<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

txtUsuario.Attributes.Add ("заполнитель", "текст");

Эвертон Люк
источник
0

вы также можете сделать это, если щелкнуть мышью, предположим, что ваш заполнитель текста "User_Name"

 private void textBox1_MouseClick(object sender, MouseEventArgs e)
 {
     if(textBox1.Text == "User_Name")
          textBox1.Text = "";
 }
Adiii
источник
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
источник
5
Вопрос уже решен, какова добавленная стоимость этого ответа? Там нет объяснения добавить все, попробуйте объяснить это.
Янник
0

Вместо использования свойства .Text TextBox я наложил TextBlock с помощью заполнителя. Я не мог использовать свойство .Text, потому что оно было привязано к событию.

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

Результат: введите описание изображения здесь

Энди
источник
0

Вы также можете попробовать таким образом ..

вызвать функцию

TextboxPlaceHolder(this.textBox1, "YourPlaceHolder");

написать эту функцию

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

Есть ЛУЧШЕЕ решение, но самое простое решение здесь: установите текстовое поле на желаемую строку, затем создайте функцию, которая удаляет текст, запустите эту функцию в текстовом поле.

Джаред
источник
0

Я написал настраиваемый элемент управления многократного использования, возможно, он может помочь кому-то, кому необходимо реализовать несколько текстовых полей-заполнителей в своем проекте.
Вот пользовательский класс с примером реализации экземпляра, который вы можете легко протестировать, вставив этот код в новый проект winforms, используя 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
источник
-1

Очень эффективное решение здесь для управления WindowsForms TextBox. (не уверен насчет XAML).

Это также будет работать в режиме Multliline.

Возможно, он может быть расширен для других элементов управления, например, для элемента управления ComboBox (не проверено)

Антон Норко
источник
-1

Работает как шарм.

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);
        }
    }
}
Сергей
источник
Пожалуйста , добавьте usings необходимо
Акку