How can I add a hint text to WPF textbox?

.NetWpfUser InterfaceTextbox

.Net Problem Overview


For example, Facebook has a "Search" hint text in the Search text box when the textbox is empty.

How to achieve this with WPF text boxes??

Facebook's search textbox

.Net Solutions


Solution 1 - .Net

You can accomplish this much more easily with a VisualBrush and some triggers in a 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>

To increase the re-usability of this Style, you can also create a set of attached properties to control the actual cue banner text, color, orientation etc.

Solution 2 - .Net

This is my simple solution, adapted from 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}}" IsHitTestVisible="False"/>
        <!-- enter term here -->
        <TextBox MinWidth="50" Name="txtSearchBox" Background="Transparent" />
    </Grid>

Solution 3 - .Net

what about using materialDesign HintAssist ? i'm using this which also you can add floating hint too :

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

i installed Material Design with Nuget Package there is installation guide in documentation link

Solution 4 - .Net

Do it in the code-behind by setting the text color initially to gray and adding event handlers for gaining and losing keyboard focus.

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

Then the event handlers:

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

Solution 5 - .Net

You have to create a custom control by inheriting the textbox. Below link has an excellent example about the search textbox sample. Please have a look at this

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

Solution 6 - .Net

You can do in a very simple way. The idea is to place a Label in the same place as your textbox. Your Label will be visible if textbox has no text and hasn't the focus.

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

Bonus:If you want to have default value for your textBox, be sure after to set it when submitting data (for example:"InputText"="PlaceHolder Text Here" if empty).

Solution 7 - .Net

I once got into the same situation, I solved it following way. I've only fulfilled the requirements of a hint box, you can make it more interactive by adding effects and other things on other events like on focus etc.

WPF CODE (I've removed styling to make it readable)

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

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

Solution 8 - .Net

Another approach ;-)

this works also with PasswordBox. If you want to use it with TextBox, simply exchange PasswordChangedwith 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;
    }
}

Solution 9 - .Net

Another solution is to use a WPF toolkit like MahApps.Metro. It has many nice features, like a text box watermark:

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

See http://mahapps.com/controls/textbox.html

Solution 10 - .Net

I used the got and lost focus events:

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

It works well, but the text is in gray still. Needs cleaning up. I was using VB.NET

Solution 11 - .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>

Solution 12 - .Net

That's my take:

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

Most other answers including the top one have flaws in my opinion.

This solution works under all circumstances. Pure XAML, easily reusable.

Solution 13 - .Net

I accomplish this with a VisualBrush and some triggers in a Style suggested by :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 :Application running, bt Design not loading...the following Error comes: Ambiguous type reference. A type named 'StaticExtension' occurs in at least two namespaces, 'MS.Internal.Metadata.ExposedTypes.Xaml' and 'System.Windows.Markup'. Consider adjusting the assembly XmlnsDefinition attributes. 'm using .net 3.5

Solution 14 - .Net

For WPF, there isn't a way. You have to mimic it. See this example. A secondary (flaky solution) is to host a WinForms user control that inherits from TextBox and send the EM_SETCUEBANNER message to the edit control. ie.

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

Also, if you want to host a WinForm control approach, I have a framework that already includes this implementation called BitFlex Framework, which you can download for free here.

Here is an article about BitFlex if you want more information. You will start to find that if you are looking to have Windows Explorer style controls that this generally never comes out of the box, and because WPF does not work with handles generally you cannot write an easy wrapper around Win32 or an existing control like you can with WinForms.

Screenshot: enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLouis RhysView Question on Stackoverflow
Solution 1 - .NetsellmeadogView Answer on Stackoverflow
Solution 2 - .NetMartin SchmidtView Answer on Stackoverflow
Solution 3 - .NetMahdi KhaliliView Answer on Stackoverflow
Solution 4 - .Netmxgg250View Answer on Stackoverflow
Solution 5 - .NetKishore KumarView Answer on Stackoverflow
Solution 6 - .NetmakertooView Answer on Stackoverflow
Solution 7 - .NetMohammad MahrozView Answer on Stackoverflow
Solution 8 - .NetMatView Answer on Stackoverflow
Solution 9 - .NetStefanGView Answer on Stackoverflow
Solution 10 - .NetStarLordBlairView Answer on Stackoverflow
Solution 11 - .NetDerBesondereEinView Answer on Stackoverflow
Solution 12 - .NetJulianView Answer on Stackoverflow
Solution 13 - .NetSUHAIL AGView Answer on Stackoverflow
Solution 14 - .NetDavid AndersonView Answer on Stackoverflow