How to add Watermark Text to TextBox and PasswordBox in WPF

No.of Views2670
Bookmarked0 times
Downloads 
Votes2
By  Prabu   On  23 Jun 2010 10:06:08
Tag : WPF , Edit Controls
I had a requirement in my sample application to show the watermark text (Help text) in input TextBox and PasswordBox (like Win7 Style of authentication)
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

I had a requirement in my sample application to show the watermark text (Help text) in input TextBox and PasswordBox (like Win7 Style of authentication). After a few minutes of search through internet, I got lots of sample application for showing watermark text in TextBox. But I couldn't get a sample application for showing watermark text to the PasswordBox.

Since the PasswordBox is a sealed class, you cannot inherit a custom class from PasswordBox. Also Password property is not a dependency property hence you cannot write triggers. Hence I have created a custom class with attached properties such as IsMonitoring (for monitoring the input), TextLength (for finding the input text length) and HasText (for showing the watermark text).

The following code and style will help you to achieve this functionality.

WaterMarkTextHelper class

public class WaterMarkTextHelper : DependencyObject
    {public static bool GetIsMonitoring(DependencyObject obj)
        {return (bool)obj.GetValue(IsMonitoringProperty);
        }public static void SetIsMonitoring(DependencyObject obj, bool value)
        {
            obj.SetValue(IsMonitoringProperty, value);
        }public static readonly DependencyProperty IsMonitoringProperty =
            DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(WaterMarkTextHelper), new UIPropertyMetadata(false, OnIsMonitoringChanged));public static int GetTextLength(DependencyObject obj)
        {return (int)obj.GetValue(TextLengthProperty);
        }public static void SetTextLength(DependencyObject obj, int value)
        {
            obj.SetValue(TextLengthProperty, value);if (value >= 1)
                obj.SetValue(HasTextProperty, true);elseobj.SetValue(HasTextProperty, false);
        }public static readonly DependencyProperty TextLengthProperty =
            DependencyProperty.RegisterAttached("TextLength", typeof(int), typeof(WaterMarkTextHelper), new UIPropertyMetadata(0));private static readonly DependencyProperty HasTextProperty = 
            DependencyProperty.RegisterAttached("HasText", typeof(bool), typeof(WaterMarkTextHelper), new FrameworkPropertyMetadata(false));public bool HasText
        {get { return (bool)GetValue(HasTextProperty); }set { SetValue(HasTextProperty, value); }
        }private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {if (d is TextBox)
            {
                TextBox txtBox = d as TextBox;if ((bool)e.NewValue)
                    txtBox.TextChanged += TextChanged;elsetxtBox.TextChanged -= TextChanged;
            }else if (d is PasswordBox)
            {
                PasswordBox passBox = d as PasswordBox;if ((bool)e.NewValue)
                    passBox.PasswordChanged += PasswordChanged;elsepassBox.PasswordChanged -= PasswordChanged;
            }
        }static void TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox txtBox = sender as TextBox;if (txtBox == null) return;
            SetTextLength(txtBox, txtBox.Text.Length);
        }static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox passBox = sender as PasswordBox;if (passBox == null) return;
            SetTextLength(passBox, passBox.Password.Length);
        }
    }

XAML Styles

 

<Style x:Key="{x:Type PasswordBox}" TargetType="{x:Type PasswordBox}"><Setter Property="local:WaterMarkTextHelper.IsMonitoring" Value="True"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type PasswordBox}"><ControlTemplate.Resources><Storyboard x:Key="enterGotFocus" ><DoubleAnimation Duration="0:0:0.4" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="exitGotFocus" ><DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="enterHasText" ><DoubleAnimation Duration="0:0:0.4" From=".2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="exitHasText" ><DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard></ControlTemplate.Resources><Border Name="Bd"Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"><Grid><ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Margin="3" /><TextBlock Text="Password" x:Name="Message"Foreground="Navy" IsHitTestVisible="False" FontFamily="Calibri"Opacity="0.5" HorizontalAlignment="Left" VerticalAlignment="Center"Margin="6,0,0,0"/></Grid></Border><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="false"><Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="local:WaterMarkTextHelper.HasText" Value="False"/><Condition Property="IsFocused" Value="True"/></MultiTrigger.Conditions><MultiTrigger.EnterActions><BeginStoryboard Storyboard="{StaticResource enterGotFocus}"/></MultiTrigger.EnterActions><MultiTrigger.ExitActions><BeginStoryboard Storyboard="{StaticResource exitGotFocus}"/></MultiTrigger.ExitActions></MultiTrigger><Trigger Property="local:WaterMarkTextHelper.HasText" Value="True"><Trigger.EnterActions><BeginStoryboard Storyboard="{StaticResource enterHasText}"/></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard Storyboard="{StaticResource exitHasText}"/></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}"><Setter Property="local:WaterMarkTextHelper.IsMonitoring" Value="True"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type TextBox}"><ControlTemplate.Resources><Storyboard x:Key="enterGotFocus" ><DoubleAnimation Duration="0:0:0.4" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="exitGotFocus" ><DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="enterHasText" ><DoubleAnimation Duration="0:0:0.4" From=".2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard><Storyboard x:Key="exitHasText" ><DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/></Storyboard></ControlTemplate.Resources><Border Name="Bd"Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"><Grid><ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Margin="3" /><TextBlock Text="Username" x:Name="Message"Foreground="Navy" IsHitTestVisible="False" FontFamily="Calibri"Opacity="0.5" HorizontalAlignment="Left" VerticalAlignment="Center"Margin="6,0,0,0"/></Grid></Border><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="false"><Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="local:WaterMarkTextHelper.HasText" Value="False"/><Condition Property="IsFocused" Value="True"/></MultiTrigger.Conditions><MultiTrigger.EnterActions><BeginStoryboard Storyboard="{StaticResource enterGotFocus}"/></MultiTrigger.EnterActions><MultiTrigger.ExitActions><BeginStoryboard Storyboard="{StaticResource exitGotFocus}"/></MultiTrigger.ExitActions></MultiTrigger><Trigger Property="local:WaterMarkTextHelper.HasText" Value="True"><Trigger.EnterActions><BeginStoryboard Storyboard="{StaticResource enterHasText}"/></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard Storyboard="{StaticResource exitHasText}"/></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

Sample Output

Image Loading

Sample Project Source

Download source files -9 kb

 
Sign Up to vote for this article
 
About Author
 
Prabu
Occupation-Software Engineer
Company-
Member Type-Fresh
Location-India
Joined date-23 Jun 2010
Home Page-
Blog Page-http://prabu-guru.blogspot.com/
 
 
Other popularSectionarticles
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top