WPF Watermark PasswordBox by Watermark TextBox

I use the Watermark text box, as in the Watermark TextBox in WPF

<Grid Grid.Row="0" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" > <TextBlock Margin="5,2" Text="This prompt dissappears as you type..." Foreground="{StaticResource brushWatermarkForeground}" Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" /> <TextBox Name="txtUserEntry" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" /> </Grid> 

How can I apply this for PasswordBox?

+4
source share
4 answers

The general approach is the same: you write a user management style and show a watermark when the password field is empty. The only problem is that the PasswordBox.Password property is not a dependency property, and you cannot use it in a trigger. Also, PasswordBox is sealed, so you cannot override this notification behavior. But you can use the attached properties here. The following code demonstrates how.

Xaml

 <Window x:Class="WpfTest.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfTest="clr-namespace:WpfTest" Title="Password Box Sample" Height="300" Width="300"> <Window.Resources> <Style x:Key="{x:Type PasswordBox}" TargetType="{x:Type PasswordBox}"> <Setter Property="WpfTest:PasswordBoxMonitor.IsMonitoring" Value="True"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type PasswordBox}"> <Border Name="Bd" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true"> <Grid> <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> <TextBlock Text="Please enter your password" Margin="4, 2, 0, 0" Foreground="Gray" Visibility="Collapsed" Name="txtPrompt" /> </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> <Trigger Property="WpfTest:PasswordBoxMonitor.PasswordLength" Value="0"> <Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid> <PasswordBox VerticalAlignment="Top"/> </Grid> </Window> 

FROM#

 using System.Windows; using System.Windows.Controls; namespace WpfTest { public partial class Window1 : Window { public Window1() { InitializeComponent(); } } public class PasswordBoxMonitor : 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(PasswordBoxMonitor), new UIPropertyMetadata(false, OnIsMonitoringChanged)); public static int GetPasswordLength(DependencyObject obj) { return (int)obj.GetValue(PasswordLengthProperty); } public static void SetPasswordLength(DependencyObject obj, int value) { obj.SetValue(PasswordLengthProperty, value); } public static readonly DependencyProperty PasswordLengthProperty = DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxMonitor), new UIPropertyMetadata(0)); private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var pb = d as PasswordBox; if (pb == null) { return; } if ((bool) e.NewValue) { pb.PasswordChanged += PasswordChanged; } else { pb.PasswordChanged -= PasswordChanged; } } static void PasswordChanged(object sender, RoutedEventArgs e) { var pb = sender as PasswordBox; if (pb == null) { return; } SetPasswordLength(pb, pb.Password.Length); } } } 

Pay attention to PasswordBoxMonitor in the XAML code.

+15
source

you can show / hide the background yourself, and not use triggers:

XAML:

 <PasswordBox x:Name="passwordBox" PasswordChanged="passwordChanged" Background="{StaticResource PasswordHint}" /> 

Code behind:

 // helper to hide watermark hint in password field private void passwordChanged(object sender, RoutedEventArgs e) { if (passwordBox.Password.Length == 0) passwordBox.Background.Opacity = 1; else passwordBox.Background.Opacity = 0; } 
+8
source

you can use my approach for watermarking behavior. all you have to do is copy and paste the TextBoxWatermarkBehavior and change the Behavior<TextBox> to Behavior<PasswordBox> .

you can find the demo project here

+3
source

@blindmeis a good suggestion . For PasswordBox, the class will look like this.

 public class PasswordBoxWatermarkBehavior : System.Windows.Interactivity.Behavior<PasswordBox> { private TextBlockAdorner adorner; private WeakPropertyChangeNotifier notifier; #region DependencyProperty's public static readonly DependencyProperty LabelProperty = DependencyProperty.RegisterAttached("Label", typeof(string), typeof(PasswordBoxWatermarkBehavior)); public string Label { get { return (string)GetValue(LabelProperty); } set { SetValue(LabelProperty, value); } } public static readonly DependencyProperty LabelStyleProperty = DependencyProperty.RegisterAttached("LabelStyle", typeof(Style), typeof(PasswordBoxWatermarkBehavior)); public Style LabelStyle { get { return (Style)GetValue(LabelStyleProperty); } set { SetValue(LabelStyleProperty, value); } } #endregion protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.Loaded += this.AssociatedObjectLoaded; this.AssociatedObject.PasswordChanged += AssociatedObjectPasswordChanged; } protected override void OnDetaching() { base.OnDetaching(); this.AssociatedObject.Loaded -= this.AssociatedObjectLoaded; this.AssociatedObject.PasswordChanged -= this.AssociatedObjectPasswordChanged; this.notifier = null; } private void AssociatedObjectPasswordChanged(object sender, RoutedEventArgs e) { this.UpdateAdorner(); } private void AssociatedObjectLoaded(object sender, System.Windows.RoutedEventArgs e) { this.adorner = new TextBlockAdorner(this.AssociatedObject, this.Label, this.LabelStyle); this.UpdateAdorner(); //AddValueChanged for IsFocused in a weak manner this.notifier = new WeakPropertyChangeNotifier(this.AssociatedObject, UIElement.IsFocusedProperty); this.notifier.ValueChanged += new EventHandler(this.UpdateAdorner); } private void UpdateAdorner(object sender, EventArgs e) { this.UpdateAdorner(); } private void UpdateAdorner() { if (!String.IsNullOrEmpty(this.AssociatedObject.Password) || this.AssociatedObject.IsFocused) { // Hide the Watermark Label if the adorner layer is visible this.AssociatedObject.TryRemoveAdorners<TextBlockAdorner>(); } else { // Show the Watermark Label if the adorner layer is visible this.AssociatedObject.TryAddAdorner<TextBlockAdorner>(adorner); } } } 
0
source

All Articles