Introduction
A lot of the examples I found on how to add a watermark to a TextBox involve a significant amount of code-behind, handling text changed events, or making use of a custom IValueConverter
or IMultiValueConverter
. In this article, I'll show how to add a watermark to a TextBox by only using XAML markup.
Background
A demonstration project I recently worked on was pre-setting the text of a textbox as kind of a poor-man's watermark. But when you started typing in the box, you have to first clear away the default value. That's not a watermark, that's just annoying. I wanted to fix this, but I didn't want to write a bunch of C# code to make it happen. I knew it could be done in XAML.
Using the code
Let's just jump right to it
<Grid x:Name="WatermarkWrapper">
<TextBox x:Name="WaterMarkedTextBox" Text="{Binding Text, FallbackValue='Hello World'}" />
<TextBlock IsHitTestVisible="False" Text="{Binding WatermarkText}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Text}" Value="" />
<Condition Binding="{Binding ElementName=WaterMarkedTextBox, Path=IsKeyboardFocused}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Visibility" Value="Visible" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
First we wrap everthing in a Grid
. We'll use this as a container to define our overall layout. Then we add our TextBox
for user input, and our TextBlock
as our watermark. Since we don't specify row and column definitions, these controls will overlap - and we want that; a watermark should visually appear on top of a textbox. On our TextBlock however, we don't want it be included in any hit test results, so we'll set the IsHitTestVisible property to false.
For the TextBlock
's style, we'll default it to collapsed, and then set it to visible when our DataContext's Text property does not have content AND when the TextBox does not have keyboard focus.
And that's it! No converters, no extensions, just pure XAML.
Credits
History
2015-03-04 : Initial post