Как добавить текст подсказки в текстовое поле WPF?
Например, у Facebook есть текст подсказки "Поиск" в текстовом поле "Поиск", когда текстовое поле пустое.
Как этого добиться с помощью текстовых полей WPF??
12 ответов
Вы можете сделать это намного проще с 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
Вы также можете создать набор прикрепленных свойств для управления фактическим текстом, цветом, ориентацией баннера и т. д.
Это мое простое решение, адаптированное от 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>
А как насчет использования материалов дизайна HintAssist? Я использую это, что вы также можете добавить плавающую подсказку:
<TextBox Width="150" Height="40" Text="hello" materialDesign:HintAssist.Hint="address" materialDesign:HintAssist.IsFloating="True"></TextBox>
я установил Material Design с Nuget Package, руководство по установке находится в ссылке на документацию
Сделайте это с помощью кода, установив сначала цвет текста на серый и добавив обработчики событий для получения и потери фокуса клавиатуры.
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";
}
}
}
Вы должны создать пользовательский элемент управления, унаследовав текстовое поле. Ниже ссылка имеет отличный пример о поиске образца текстового поля. Пожалуйста, посмотрите на это
http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/
Вы можете сделать это очень простым способом. Идея состоит в том, чтобы разместить ярлык в том же месте, что и текстовое поле. Ваша Метка будет видна, если текстовое поле не имеет текста и не имеет фокуса.
<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"="PlaceHolder Text Here", если он пуст).
Однажды я попал в ту же ситуацию, я решил ее следующим образом. Я только выполнил требования подсказки, вы можете сделать ее более интерактивной, добавив эффекты и другие вещи в другие события, такие как фокус и т. Д.
WPF CODE (я удалил стиль, чтобы сделать его читабельным)
<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;
}
}
Другой подход;-)
это работает также с 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;
}
}
Другим решением является использование инструментария WPF, такого как MahApps.Metro. Он имеет много приятных функций, таких как текстовое поле водяного знака:
Controls:TextBoxHelper.Watermark="Search..."
Я использовал полученные и потерянные события фокуса:
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
<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>
Это мое мнение:
<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, легко повторно используемый.
Я делаю это с 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 Design не загружается... появляется следующая ошибка: двусмысленная ссылка на тип. Тип с именем "StaticExtension" встречается как минимум в двух пространствах имен: "MS.Internal.Metadata.ExposedTypes.Xaml" и "System.Windows.Markup". Попробуйте настроить атрибуты сборки XmlnsDefinition. использую.net 3.5
Для 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, то, как правило, они никогда не выходят из коробки, а поскольку WPF не работает с дескрипторами, вы, как правило, не можете написать простую оболочку для Win32 или существующий элемент управления. с WinForms.
Скриншот: