Tuesday, May 19, 2009

WatermarkTextBox by inheriting TextBox

I am very happy to see that my previous post “WPF Watermark TextBox using XAML Style” helped a lot of peoples to solve their issues and currently that is the most popular post in my blog.That post describes about creating a WPF watermark textbox by changing it’s style.All the things are done in xaml and there is no property to set the water mark text.
There was a requirement from one of the readers for such a property.ie a Watermark property which decides the watermark text.So rewriting the sample with that property.
Here I just derived a new class called WatemarkTextBox from standard TextBox added a new dependency property called Watermark and defined default style for that control in generic.xaml.The steps are as follows

  1. Subclass TextBox and create a new class called WatermarkTextBox.
  2. Add a new DP called Watermark which is of type object.
  3. In the generic.xaml write the default style.
public class WatermarkTextBox : TextBox
{
static WatermarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox),
new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
}

public object Watermark
{
get { return (object)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
// Using a DependencyProperty as the backing store for Watermark. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
"Watermark",
typeof(object),
typeof(WatermarkTextBox),
new UIPropertyMetadata(null));
}

And its style in generic.xaml contains almost same elements as of my last post.But here I have used TemplateBinding to set Watermark into the TextBlock.

<Style TargetType="{x:Type local:WatermarkTextBox}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush"
Value="Blue" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Padding"
Value="1" />
<Setter Property="AllowDrop"
Value="true" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:WatermarkTextBox}">
<Grid>
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd"
SnapsToDevicePixels="true"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
RenderFocused="{TemplateBinding IsKeyboardFocusWithin}"
RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Microsoft_Windows_Themes:ListBoxChrome>
<TextBlock x:Name="textBlock"
Opacity="0.345"
Text="{TemplateBinding Watermark}"
TextWrapping="Wrap"
Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="textBlock"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Download sample from here.

5 Comments:

bradutz01 said...

Hi, very nice maybe they will include a control like that in theyr framework and then i will style it as you can see on my website (http://www.xamltemplates.net/)

Anonymous said...

plz include a sample on dependency property

Joymon | ജോയ് മോന്‍ | जोय मोन | ஜோய் மோன் said...

If my understanding about your comment is right the sample is already there in skydrive.
http://cid-890c06c8106550a0.skydrive.live.com/self.aspx/BlogSamples/JoyfulWPF/WatermarkTextBox.zip

Are you looking for something else?

Dr Web Monkey said...

The following change to the original watermark post makes the watermark changable.

Instead of Text="Enter Text Here"
Use Text="{TemplateBinding Tag}"

Then you can use Tag="Enter your Text here" for the watermark text.

I just came across this Tag templatebinding, so there may be a better way...

Joymon | ജോയ് മോന്‍ | जोय मोन | ஜோய் மோன் said...

Tag...I forgot.
Thats good idea.Thanks for sharing...

Post a Comment