Як я можу додати текст підказки до текстового поля WPF?


107

Наприклад, Facebook має текст підказки "Пошук" у текстовому полі "Пошук", коли текстове поле порожнє.

Як цього досягти за допомогою текстових полів WPF ??

Текстове поле пошуку у Facebook


2
Спробуйте здійснити пошук "банеру з написом".
локальне місце за замовчуванням

@MAKKAM ця стаття MSDN обговорює це, але в ній не показано, як це робиться
Louis Rhys


1
Я б не називав те, що ви просите, для "підказки". для мене натяк текст - це спливаюче вікно. все-таки я знайшов це питання, коли хотів налаштувати текст заповнення. і відповіді нижче мені допомогли.
Стів

1
Це називається водяним знаком до речі
Blechdose

Відповіді:


158

Ви можете зробити це набагато простіше за допомогою a VisualBrushі деяких тригерів у Style:

<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <Style.Resources>
                <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                    <VisualBrush.Visual>
                        <Label Content="Search" Foreground="LightGray" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Style.Resources>
            <Style.Triggers>
                <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="Text" Value="{x:Null}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter Property="Background" Value="White" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

Щоб збільшити повторну корисність цього Style, ви також можете створити набір доданих властивостей для управління фактичним текстом банера, кольором, орієнтацією тощо.


1
Використовуйте IsMouseCappted замість IsKeyboardFocused. Ось так реагує справжній банер-кий.
Монсьє,

5
Якщо хто - небудь задавалися питанням, як використовувати вкладені властивості для поліпшення стилю повторного см: stackoverflow.com/a/650620/724944
сурфен

@Kurian IsMouseCappted зробить кий зникнути лише після натискання на нього мишкою, але з’явиться знову, коли ви відпустите кнопку миші. Це не добре виглядає. IsMouseOver також не був би хорошим (клавіатура має фокус, але вказівник миші знаходиться в іншому місці => відображається кия). Більшість банерів київ використовують IsKeyboardFocused (наприклад, Facebook), і я думаю, що це добре. Альтернативним рішенням буде використання обох тригерів: (IsMouseOver OR IsKeyboardFocused)
серфінг

23
Рішення має бути натяком = "Будь ласка, введіть свій текст", а не 20 елементів ... На жаль, це не підтримується легендарним вбудованим текстовим полем ...
Mzn

8
Незважаючи на те, що за умовчанням цей підхід може бути нормальним, він не працює, коли ваше текстове поле вже містить фонову кисть або фон форми не такого кольору, як текстове поле.
LWChris

56

Це моє просте рішення, адаптоване від Microsoft ( https://code.msdn.microsoft.com/windowsapps/How-to-add-a-hint-text-to-ed66a3c6 )

    <Grid Background="White" HorizontalAlignment="Right" VerticalAlignment="Top"  >
        <!-- overlay with hint text -->
        <TextBlock Margin="5,2" MinWidth="50" Text="Suche..." 
                   Foreground="LightSteelBlue" Visibility="{Binding ElementName=txtSearchBox, Path=Text.IsEmpty, Converter={StaticResource MyBoolToVisibilityConverter}}" />
        <!-- enter term here -->
        <TextBox MinWidth="50" Name="txtSearchBox" Background="Transparent" />
    </Grid>

Цікавий підхід, я б не одразу подумав про себе.
itsmatt

приємно і просто :)
shmulik.r

3
Це рішення особливо добре працює, якщо встановити TextBlock наIsHitTestVisible="False"
Mage Xy

1
@MageXy посилається на перший TextBlock (підказки).
Фелікс

Це рішення чудово працює, якщо ви хочете прив’язати текст підказки до властивості.
PeterB

11

як щодо використання materialDesign HintAssist? Я використовую це, що також ви можете додати плаваючу підказку:

<TextBox Width="150" Height="40" Text="hello" materialDesign:HintAssist.Hint="address"  materialDesign:HintAssist.IsFloating="True"></TextBox>

я встановив Material Design за допомогою Nuget Package, у посиланні на документацію є посібник з установки


2
Дуже корисна бібліотека
AlexF11

9

Зробіть це за допомогою коду, встановивши колір тексту спочатку сірий та додавши обробники подій для отримання та втрати фокусу на клавіатурі.

TextBox tb = new TextBox();
tb.Foreground = Brushes.Gray;
tb.Text = "Text";
tb.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_GotKeyboardFocus);
tb.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(tb_LostKeyboardFocus);

Тоді обробники подій:

private void tb_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    if(sender is TextBox)
    {
        //If nothing has been entered yet.
        if(((TextBox)sender).Foreground == Brushes.Gray)
        {
            ((TextBox)sender).Text = "";
            ((TextBox)sender).Foreground = Brushes.Black;
        }
    }
}


private void tb_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    //Make sure sender is the correct Control.
    if(sender is TextBox)
    {
        //If nothing was entered, reset default text.
        if(((TextBox)sender).Text.Trim().Equals(""))
        {
            ((TextBox)sender).Foreground = Brushes.Gray;
            ((TextBox)sender).Text = "Text";
        }
    }
}

7
-1 для цього в коді позаду: захаращує керування, і є велика ймовірність, що це буде заважати іншій логіці управління, якщо не зараз, то в майбутньому.
ОлексійOst

5

Ви повинні створити спеціальний елемент управління, успадкувавши текстове поле. Нижче посилання має відмінний приклад про зразок пошукового текстового поля. Будь ласка, подивіться на це

http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/


2
Відповіді, що стосуються лише посилань, не відволікають
Josh Noe

4

Це можна зробити дуже простим способом. Ідея полягає в тому, щоб розмістити мітку там же, що і ваші текстові поля. Ваша мітка буде видно, якщо в текстовому полі немає тексту та немає фокусу.

 <Label Name="PalceHolder"  HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40" VerticalAlignment="Top" Width="239" FontStyle="Italic"  Foreground="BurlyWood">PlaceHolder Text Here
  <Label.Style>
    <Style TargetType="{x:Type Label}">
      <Setter Property="Visibility" Value="Hidden"/>
      <Style.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding ="{Binding ElementName=PalceHolder, Path=Text.Length}" Value="0"/>
            <Condition Binding ="{Binding ElementName=PalceHolder, Path=IsFocused}" Value="False"/>
          </MultiDataTrigger.Conditions>
          <Setter Property="Visibility" Value="Visible"/>
        </MultiDataTrigger>
      </Style.Triggers>
    </Style>
  </Label.Style>
</Label>
<TextBox  Background="Transparent" Name="TextBox1" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40"TextWrapping="Wrap" Text="{Binding InputText,Mode=TwoWay}" VerticalAlignment="Top" Width="239" />

Бонус: Якщо ви хочете мати значення тексту textBox за замовчуванням, обов'язково встановіть його під час подання даних (наприклад: "InputText" = "Тут розміщено текст тексту", якщо порожній).


2

Інший підхід ;-)

це також працює з PasswordBox. Якщо ви хочете ним користуватися TextBox, просто обміняйтеся PasswordChangedз ними TextChanged.

XAML:

<Grid>
    <!-- overlay with hint text -->
    <TextBlock Margin="5,2"
                Text="Password"
                Foreground="Gray"
                Name="txtHintPassword"/>
    <!-- enter user here -->
    <PasswordBox Name="txtPassword"
                Background="Transparent"
                PasswordChanged="txtPassword_PasswordChanged"/>
</Grid>

CodeBehind:

private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
{
    txtHintPassword.Visibility = Visibility.Visible;
    if (txtPassword.Password.Length > 0)
    {
        txtHintPassword.Visibility = Visibility.Hidden;
    }
}

Найкраще і найпростіше рішення, яке я знайшов !! Дякую!!
Стів

2

Я одного разу потрапив у ту саму ситуацію, я вирішив це наступним чином. Я лише виконав вимоги до підказки, ви можете зробити його більш інтерактивним, додаючи ефекти та інші речі на інші події, наприклад, на фокус тощо.

WPF КОД (я видалив стайлінг, щоб зробити його читабельним)

<Grid Margin="0,0,0,0"  Background="White">
    <Label Name="adminEmailHint" Foreground="LightGray" Padding="6"  FontSize="14">Admin Email</Label>
    <TextBox Padding="4,7,4,8" Background="Transparent" TextChanged="adminEmail_TextChanged" Height="31" x:Name="adminEmail" Width="180" />
</Grid>
<Grid Margin="10,0,10,0" Background="White" >
    <Label Name="adminPasswordHint" Foreground="LightGray" Padding="6"  FontSize="14">Admin Password</Label>
    <PasswordBox Padding="4,6,4,8" Background="Transparent" PasswordChanged="adminPassword_PasswordChanged" Height="31" x:Name="adminPassword" VerticalContentAlignment="Center" VerticalAlignment="Center" Width="180" FontFamily="Helvetica" FontWeight="Light" FontSize="14" Controls:TextBoxHelper.Watermark="Admin Password"  FontStyle="Normal" />
</Grid>

C # код

private void adminEmail_TextChanged(object sender, TextChangedEventArgs e)
    {
        if(adminEmail.Text.Length == 0)
        {
            adminEmailHint.Visibility = Visibility.Visible;
        }
        else
        {
            adminEmailHint.Visibility = Visibility.Hidden;
        }
    }

private void adminPassword_PasswordChanged(object sender, RoutedEventArgs e)
    {
        if (adminPassword.Password.Length == 0)
        {
            adminPasswordHint.Visibility = Visibility.Visible;
        }
        else
        {
            adminPasswordHint.Visibility = Visibility.Hidden;
        }
    }

1

Іншим рішенням є використання інструментарію WPF на зразок MahApps.Metro. Він має багато приємних функцій, як водяний знак текстового поля:

Controls:TextBoxHelper.Watermark="Search..."

Див. Http://mahapps.com/controls/textbox.html


0

Я використовував отримані та втрачені фокус події:

Private Sub txtSearchBox_GotFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles txtSearchBox.GotFocus
    If txtSearchBox.Text = "Search" Then
        txtSearchBox.Text = ""
    Else

    End If

End Sub

Private Sub txtSearchBox_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles txtSearchBox.LostFocus
    If txtSearchBox.Text = "" Then
        txtSearchBox.Text = "Search"
    Else

    End If
End Sub

Це добре працює, але текст все-таки сірим кольором. Потребує прибирання. Я використовував VB.NET


0
  <Grid>
    <TextBox Name="myTextBox"/>
    <TextBlock>
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=myTextBox, Path=Text.IsEmpty}" Value="True">
                        <Setter Property="Text" Value="Prompt..."/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</Grid>

0

Ось мій:

<ControlTemplate>
    <Grid>
        <Grid.Resources>
            <!--Define look / layout for both TextBoxes here. I applied custom Padding and BorderThickness for my application-->
            <Style TargetType="TextBox">
                <Setter Property="Padding" Value="4"/>
                <Setter Property="BorderThickness" Value="2"/>
            </Style>
        </Grid.Resources>

        <TextBox x:Name="TbSearch"/>
        <TextBox x:Name="TbHint" Text="Suche" Foreground="LightGray"
                 Visibility="Hidden" IsHitTestVisible="False" Focusable="False"/>
    </Grid>

    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition SourceName="TbSearch" Property="Text" Value="{x:Static sys:String.Empty}"/>
                <Condition SourceName="TbSearch" Property="IsKeyboardFocused" Value="False"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter TargetName="TbHint" Property="Visibility" Value="Visible"/>
            </MultiTrigger.Setters>
        </MultiTrigger>

        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition SourceName="TbSearch" Property="Text" Value="{x:Null}"/>
                <Condition SourceName="TbSearch" Property="IsKeyboardFocused" Value="False"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter TargetName="TbHint" Property="Visibility" Value="Visible"/>
            </MultiTrigger.Setters>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Більшість інших відповідей, включаючи верхню, на мій погляд, мають вади.

Це рішення працює за будь-яких обставин. Чистий XAML, легко використовувати багаторазово.


-1

Я роблю це з VisualBrushі деякі тригери в Styleзапропонованих: sellmeadog.

<TextBox>
        <TextBox.Style>
            <Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
                <Style.Resources>
                    <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                        <VisualBrush.Visual>
                            <Label Content="Search" Foreground="LightGray" />
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Style.Resources>
                <Style.Triggers>
                    <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                        <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                    </Trigger>
                    <Trigger Property="Text" Value="{x:Null}">
                        <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

@sellmeadog: Запуск програми, bt Дизайн не завантажується ... Приходить наступна помилка: Неоднозначне посилання типу. Тип з назвою "StaticExtension" зустрічається щонайменше у двох просторах імен, "MS.Internal.Metadata.ExposedTypes.Xaml" і "System.Windows.Markup". Розглянемо коригування атрибутів збірки XmlnsDefinition. я використовую .net 3.5


Вирішили проблему, змінивши <Trigger Property="Text" Value="{x:Static sys:String.Empty}">на<Trigger Property="Text" Value="">
SUHAIL AG

6
Схоже, це відповідь на іншу публікацію. Будь ласка, опублікуйте лише повноцінні рішення питання як відповіді.
Дрю Гейнор

4
Якщо ви вважаєте, що відповідь @ sellmeadog майже правильна, подумайте про її виправлення, замість того, щоб публікувати нову відповідь майже без різниці.
0xBADF00D

-11

Для WPF немає способу. Ви повинні наслідувати це. Дивіться цей приклад . Вторинним (лускатим рішенням) є розміщення керування користувачами WinForms, яке успадковується від TextBox та відправляє повідомлення EM_SETCUEBANNER до елемента редагування. тобто.

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

private const Int32 ECM_FIRST = 0x1500;
private const Int32 EM_SETCUEBANNER = ECM_FIRST + 1;

private void SetCueText(IntPtr handle, string cueText) {
    SendMessage(handle, EM_SETCUEBANNER, IntPtr.Zero, Marshal.StringToBSTR(cueText));
}

public string CueText {
    get {
        return m_CueText;
    } 
    set {
        m_CueText = value;
        SetCueText(this.Handle, m_CueText);
}

Крім того, якщо ви хочете розмістити підхід управління WinForm, у мене є рамка, яка вже включає цю реалізацію під назвою BitFlex Framework, яку ви можете безкоштовно завантажити тут .

Ось стаття про BitFlex, якщо ви хочете отримати додаткову інформацію. Ви почнете виявляти, що якщо ви хочете мати стилі керування Windows Explorer, що це, як правило, ніколи не виходить з коробки, і тому що WPF не працює з ручками, як правило, ви не можете написати простий обгортку навколо Win32 або наявний елемент управління, як ви можете. з WinForms.

Знімок екрана: введіть тут опис зображення


1
уау, це виглядає трохи хакітно. Як я можу це зробити під час створення керування користувачем за допомогою XAML?
Луї Різ

Ви цього не робите. Ось як це робиться. Якщо ви хочете інкапсулювати це, то зробіть керування користувачем та властивість CueText та зателефонуйте SetCueText у сеттер.
Девід Андерсон

Я думаю, що ОП повинен розміщувати елементи управління формами winforms для використання цього підходу. Або є спосіб отримати ручку текстового поля?
локальне місце за замовчуванням

Це здається чимось, що можна зробити декларативно за допомогою WPF, прив’язавшись до того, чи текстове поле має фокус чи ні, і т. Д. - Наведений вище приклад є скоріше підходом WinForms - він буде працювати в WPF, але це не правильно шлях.
BrainSlugs83

1
Вибачте, але ця відповідь просто неправильна. Також всі ланки розірвані.
Ліс Кунеке
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.