I have done the following in a new WPF project titled CustomControls
.
Step 1: Created a Controls
folder. Added a new file titled WatermarkTextBox.cs
to it. Added this C# code in the file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace Controls
{
public class WatermarkTextBox : TextBox
{
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(String), typeof(WatermarkTextBox), new PropertyMetadata(String.Empty));
public String Watermark
{
get { return (String)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
}
}
Step 2: Within the Controls
folder, added a new file titled WatermarkTextBox.xaml
. Added this XAML in the file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Controls">
<Style TargetType="{x:Type controls:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Resources>
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="{Binding Watermark}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Step 3: Create a Themes
folder. Add a new file titled Generic.xaml
to it. Add this XAML in the file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CustomControls;component/Controls/WatermarkTextBox.xaml" />
</ResourceDictionary.MergedDictionaries>
Step 4: In MainWindow.xaml
: Added xmlns:controls="clr-namespace:Controls"
, and defined a new WatermarkTextBox
:
<controls:WatermarkTextBox x:Name="Hostname" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" Watermark="Hello, world."/>
I see the text box that this custom control is based upon, but I don't see the watermark which I've extended for it. Why is that, and how may I render my watermark? P.S. I should note that the watermark DOES show up if I change {Binding Watermark}
in the XAML to a hard-coded string. Also, if I debug my code I see that WatermarkTextBox
picks up the correct value...so why is the XAML not displaying it? How can someone even debug this stuff?