13

I want to create a TextBox, which would have a gray "default" text appear in it, if it's

a) empty

b) has lost focus

when the user enters the text box, the gray "default" text should dissappear.

I've tried to do this using ControlTemplate.Triggers, but I can't seem to find HasFocus property.

What is the best way to do this using XAML?

Steve Greatrex
  • 15,789
  • 5
  • 59
  • 73
Arsen Zahray
  • 24,367
  • 48
  • 131
  • 224
  • 1
    I'd agree with @Fuji and suggest the `WatermarkTextBox`, but for future reference the `HasFocus` equivalent is `IsKeyboardFocused` http://msdn.microsoft.com/en-us/library/system.windows.uielement.iskeyboardfocused.aspx – Steve Greatrex May 03 '12 at 09:33

2 Answers2

24

Whilst there is no real benefit in re-inventing the wheel, it might be interesting to see how this can be done. The easiest way to do this (in pure XAML) is to create a ControlTemplate for the TextBox that overlays a TextBlock when it is not focussed and does not contain text:

<ControlTemplate TargetType="TextBox">
<Grid>
    <TextBox Text="{Binding Text, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Text="Your Prompt Here"
                Margin="5,0,5,0"
                Foreground="#FF808080"
                FontStyle="Italic"
                IsHitTestVisible="False"
                x:Name="UserMessage"
                Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="Text" Value=""/>
            <Condition Property="IsKeyboardFocusWithin" Value="False"/>
            </MultiTrigger.Conditions>
        <Setter Property="Visibility" TargetName="UserMessage" Value="Visible"/>
    </MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>

The MultiTrigger means "set Visibility to Visible if the Text property is empty AND the TextBox does not have keyboard focus"

If you want to make this more reusable then you could create a custom control with this as it's default template and with a Dependency Property containing the prompt message

Steve Greatrex
  • 15,789
  • 5
  • 59
  • 73
  • 6
    I agree pure XAML is nice if used rarely in a simple application. I hate adding 3rd party dlls to projects unless used frequently. – eandersson May 03 '12 at 09:45
  • @fuji and its good to understand how these things actually work! – Steve Greatrex May 03 '12 at 09:53
  • @SteveGreatrex how do I create a custom control for different text for example Text="Your Prompt Here" , another text box I need the text to be "You Prompt There" . – abc cba Feb 07 '15 at 16:55
14

You could simply use the Extended WPF Toolkit's WatermarkTextBox. enter image description here

I wrote a small guide based on your comment on how you to add and use the library in your project.

Step 1) Right-click on References in your project and choose Add Reference.

Step 1

Step 2) Locate and add the dll file WPFToolkit.Extended.dll.

Step 2

Step 3) Last you need to add the XAML code.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:extToolkit="http://schemas.xceed.com/wpf/xaml/toolkit"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <extToolkit:WatermarkTextBox Watermark="Enter First Name" />
    </Grid>
</Window>

The key here is to add the reference to the dll file.

xmlns:extToolkit="http://schemas.xceed.com/wpf/xaml/toolkit"

Then you can simply use it in XAML like this.

<extToolkit:WatermarkTextBox Watermark="Enter First Name" />
MHN
  • 103
  • 2
  • 7
eandersson
  • 25,781
  • 8
  • 89
  • 110