⬆️ ⬇️

Write your Watermark TextBox and PasswordBox for Win8 / RT, Windows Phone

Sabzh



In fact, a very trivial task, but, faced with which, you can lose precious time.

So, what we have:

The WinRT XAML Toolkit carries the Watermark TextBox on its board, but has limited functionality (Watermark color schemes). In addition, the lack of Watermark PasswordBox grieves.

The following text will allow you to save 30 minutes of time by implementing and configuring a couple of simple controls). If interested - welcome under cat.



Idea



The idea is extremely simple: TextBox for text input and TextBlock for displaying Watermark. (PasswordBox and TextBlock respectively). It remains only to slyly manipulate the transparency of controls.

The presented example is for Windows 8 / RT. Implement for Windows Phone is not difficult.



WatermarkTextBox.xaml



<UserControl x:Class="Test.Controls.WatermarkTextBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Test.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="400"> <Border x:Name="brd" Background="#FFE0E0E0" VerticalAlignment="Stretch" Padding="15,5" > <Grid> <TextBlock x:Name="tbWatermark" TextWrapping="Wrap" Foreground="#FF646464" IsHitTestVisible="False" Padding="0" FontSize="14.667" VerticalAlignment="Center" Margin="0" /> <TextBox x:Name="tb" LostFocus="LostFocus" GotFocus="GotFocus" Background="{x:Null}" FontSize="11" TextChanged="Tb_OnTextChanged" Margin="0" VerticalAlignment="Center" BorderThickness="0" Padding="0" /> </Grid> </Border> </UserControl> 


')

WatermarkTextBox.cs



  public sealed partial class WatermarkTextBox : UserControl { public WatermarkTextBox() { InitializeComponent(); } private void LostFocus(object sender, RoutedEventArgs e) { CheckWatermark(); brd.Background = new SolidColorBrush(Color.FromArgb(255, 224, 224, 224)); } public void CheckWatermark() { var passwordEmpty = string.IsNullOrEmpty(tb.Text); tbWatermark.Opacity = passwordEmpty ? 100 : 0; tb.Opacity = passwordEmpty ? 0 : 100; } private void GotFocus(object sender, RoutedEventArgs e) { tbWatermark.Opacity = 0; tb.Opacity = 100; brd.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); } private void Tb_OnTextChanged(object sender, TextChangedEventArgs e) { Text = tb.Text; } #region DependencyProperty /// <summary> /// Watermark /// </summary> public string Watermark { get { return (string)GetValue(WatermarkProperty); } set { SetValue(WatermarkProperty, value); } } public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata("", WatermarkChanged)); private static void WatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkTextBox)d; var val = (string)e.NewValue; controll.tbWatermark.Text = val; } /// <summary> /// TextSize /// </summary> public int TextSize { get { return (int)GetValue(TextSizeProperty); } set { SetValue(TextSizeProperty, value); } } public static readonly DependencyProperty TextSizeProperty = DependencyProperty.Register("TextSize", typeof(int), typeof(WatermarkTextBox), new PropertyMetadata(0, TextSizeChanged)); private static void TextSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkTextBox)d; var val = (int)e.NewValue; if (val < 10){val = 10;} controll.tb.FontSize = val; controll.tbWatermark.FontSize = val; } /// <summary> /// Text /// </summary> public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata("", TextChanged)); private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkTextBox)d; var val = (string)e.NewValue; if (val == null) { controll.tb.Text = ""; return; } controll.tb.Text = val; } #endregion } 




WatermarkPasswordBox.xaml



 UserControl x:Class="Test.Controls.WatermarkPasswordBox" 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="300" d:DesignWidth="400"> <Border x:Name="brd" Background="#FFE0E0E0" VerticalAlignment="Stretch" Padding="15,5"> <Grid> <TextBlock x:Name="tbWatermark" TextWrapping="Wrap" Foreground="#FF646464" IsHitTestVisible="False" Padding="0" FontSize="14.667" VerticalAlignment="Center" Margin="0" /> <PasswordBox x:Name="pb" LostFocus="PasswordLostFocus" GotFocus="PasswordGotFocus" Background="{x:Null}" FontSize="11" PasswordChanged="Pb_OnPasswordChanged" Margin="0" VerticalAlignment="Center" BorderThickness="0" Opacity="0" Padding="0" /> </Grid> </Border> </UserControl> 




WatermarkPasswordBox.cs



  public sealed partial class WatermarkPasswordBox : UserControl { public WatermarkPasswordBox() { this.InitializeComponent(); } private void PasswordLostFocus(object sender, RoutedEventArgs e) { CheckWatermark(); brd.Background = new SolidColorBrush(Color.FromArgb(255, 224, 224, 224)); } public void CheckWatermark() { var passwordEmpty = string.IsNullOrEmpty(pb.Password); tbWatermark.Opacity = passwordEmpty ? 100 : 0; pb.Opacity = passwordEmpty ? 0 : 100; } private void PasswordGotFocus(object sender, RoutedEventArgs e) { tbWatermark.Opacity = 0; pb.Opacity = 100; brd.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); } private void Pb_OnPasswordChanged(object sender, RoutedEventArgs e) { Password = pb.Password; } #region DependencyProperty /// <summary> /// Watermark /// </summary> public string Watermark { get { return (string)GetValue(WatermarkProperty); } set { SetValue(WatermarkProperty, value); } } public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkPasswordBox), new PropertyMetadata("", WatermarkChanged)); private static void WatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkPasswordBox)d; var val = (string)e.NewValue; controll.tbWatermark.Text = val; } /// <summary> /// Password /// </summary> public string Password { get { return (string)GetValue(PasswordProperty); } set { SetValue(PasswordProperty, value); } } public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(WatermarkPasswordBox), new PropertyMetadata("", PasswordChanged)); private static void PasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkPasswordBox)d; var val = (string)e.NewValue; if (val == null) { controll.pb.Password = ""; return; } controll.pb.Password = val; } /// <summary> /// TextSize /// </summary> public int TextSize { get { return (int)GetValue(TextSizeProperty); } set { SetValue(TextSizeProperty, value); } } public static readonly DependencyProperty TextSizeProperty = DependencyProperty.Register("TextSize", typeof(int), typeof(WatermarkPasswordBox), new PropertyMetadata(0, TextSizeChanged)); private static void TextSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var controll = (WatermarkPasswordBox)d; var val = (int)e.NewValue; if (val < 10) { val = 10; } controll.pb.FontSize = val; controll.tbWatermark.FontSize = val; } #endregion } 




And simple use in any right place:



 <controls:WatermarkTextBox x:Name="WatermarkTextBox " Text="{Binding Login, Mode=TwoWay}" Watermark="Login" Grid.Row="2" Margin="10,0" TextSize="18"/> <controls:WatermarkPasswordBox x:Name="WatermarkPasswordBox" Watermark="Password" Password="{Binding Password, Mode=TwoWay}" Grid.Row="4" Margin="10,0" TextSize="18" /> 




Just do not forget your favorite line:



 xmlns:controls="using:Test.Controls" 




How it works?


Upon receipt, GotFocus / LostFocus are processed at the start / end of entering text / password. Based on the entered values, a choice is made about the display of the Text or Watermark (CheckWatermark method). When entering text / password in the appropriate field, we redirect to our newly created DependencyProperty (Tb_OnTextChanged / Pb_OnTextChanged methods). The small DependencyProperty list includes the Watermark text, the text of the main input field, the font size of the label and the text.



We continue to customize


It is not difficult to add any necessary property to your taste. Spent 10 minutes, but got complete control. I hope someone saved time.



Note


At the time of writing, I came across the Dependency Property Generator . I hope this will also save time.



Objective / non-objective criticism is welcomed.



Update




Upper left - WatermarkTextBox

Lower left - WatermarkPasswordBox

Top right - WatermarkTextBox with entered data

Lower right - WatermarkPasswordBox with the entered data and focus.

Source: https://habr.com/ru/post/179605/



All Articles