<UserControl x:Class="WatermarkTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="30"
d:DesignWidth="250">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Border>
<Grid x:Name="grid">
<TextBlock Text="{Binding Watermark, FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Border>
</UserControl>
The above code shows my WatermarkTextBox
control. In the code behind file I have set the DataContext
. I left out all the code for the DP's of the control.
public WatermarkTextBox()
{
InitializeComponent();
grid.DataContext = this;
}
I had to bind the DataContext
to the grid because otherwise the Text
properties of both the watermark and actual text wouldn't display. The problem now is that I can't set the Background
of the Border
outside of the Grid
.
I tried the code below but then only the Background
of the Border
is set and not the watermark and actual text.
public WatermarkTextBox()
{
InitializeComponent();
this.DataContext = this;
grid.DataContext = this;
}
In a UserControl like this you should never exlicitly set the DataContext to this
or anyting else, because the DataContext is usually set externally when you use the UserControl somewhere in your application. The externally applied DataContext is typically (part of) the application's view model.
You should instead change your internal bindings so that they use an explicit RelativeSource
:
<TextBlock
Text="{Binding Path=Watermark,
RelativeSource={RelativeSource AncestorType=UserControl},
FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry,
Path=Text.IsEmpty,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox
Name="txtUserEntry"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
and then remove any DataContext assignment from the UserControl's constructor.
See e.g. this answer (and many other similar) that discuss this topic in detail.