📜 ⬆️ ⬇️

Watermark for TextBox in Windows 8 applications

Recently, it has become fashionable, in addition to an explanatory inscription for TextBox, but also to write a hint on TextBox itself. It should all look like the image to attract attention. While the user has not entered anything, a hint is highlighted. If the user entered the text, the prompt is not shown. Not God knows what a complicated logic, but because Triggers were selected from the ControlTemplate in the Windows Store applications, this will have to be done not by the style, but by the new control.
Under the cut, we will be a step-by-step guide on how to develop such a component, focused on those who are the first to approach the development of their controls. For those who are already programming under the Windows Store revelations will not, but if not difficult, put recommendations in the comments, maybe someone really decides to make a good control for such a task.

Go.
Create a new Windows Store application. In Solution we add a new assembly (right-click on Solution, in the context menu Add -> New Project):

We add a new item to this assembly (right click on the project, Add -> New Item):

In the cs file of our control, we change the ancestor to TextBox:
public sealed partial class WaterMarkedTextBox : TextBox 

Also, we will have to change the markup, replacing the base component and deleting the contents:

These simple actions allowed us to get in our component all the fields and methods that the base TextBox had. The only thing that does not suit us is the lack of the ability for TextBox to show a hint. Let's redefine our TextBox descendant template, adding a TextBlock to it, to display a hint:
 <TextBox.Template> <ControlTemplate TargetType="TextBox"> <Grid> <TextBox Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" /> <TextBlock Text="{Binding WaterMark, RelativeSource={RelativeSource TemplatedParent}}" Foreground="Gray" Margin="5,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Visibility="Collapsed" IsHitTestVisible="False"/> </Grid> </ControlTemplate> </TextBox.Template> 

Since in the constructor it is still impossible to work with visual components, then we will subscribe to the component load event and we will perform all the useful work in the event handler for this event:
 public WaterMarkedTextBox() { this.InitializeComponent(); Loaded += WaterMarkedTextBox_Loaded; } 

To determine whether we have a focus on an element or not, add a field:
 private bool _isFocused; 

Well, we need DependencyProperty to store the hint text:
 /// <summary> ///    /// </summary> public string WaterMark { get { return (string)GetValue(WaterMarkProperty); } set { SetValue(WaterMarkProperty, value); } } /// <summary> /// Static part of dependency property WaterMark /// </summary> public static readonly DependencyProperty WaterMarkProperty = DependencyProperty.Register("WaterMark", typeof(string), typeof(WaterMarkedTextBox), new PropertyMetadata("")); 

Everything, we write processing of loading of a component, receiving focus of input and loss of it:
 void WaterMarkedTextBox_Loaded(object sender, RoutedEventArgs e) { var grid = (Grid)VisualTreeHelper.GetChild(this, 0); TextBox innerTextBox = (TextBox)grid.Children[0]; innerTextBox.GotFocus += WaterMarkedTextBox_GotFocus; innerTextBox.LostFocus += WaterMarkedTextBox_LostFocus; ChangeWatermarkTextVisibility(); } void WaterMarkedTextBox_LostFocus(object sender, RoutedEventArgs e) { _isFocused = false; ChangeWatermarkTextVisibility(); } void WaterMarkedTextBox_GotFocus(object sender, RoutedEventArgs e) { _isFocused = true; ChangeWatermarkTextVisibility(); } 

Well, the latest method to change the hint visibility:
 private void ChangeWatermarkTextVisibility() { var grid = (Grid)VisualTreeHelper.GetChild(this, 0); TextBlock watermarkText = (TextBlock)grid.Children[1]; if (!string.IsNullOrEmpty(Text) || _isFocused) { watermarkText.Visibility = Visibility.Collapsed; } else { watermarkText.Visibility = Visibility.Visible; } } 

We collect the decision.
Since I took the Blank App as the initial project, then I added the following markup to the main form:
 <Page x:Class="App11.MainPage" xmlns:MyControls="using:MyControls" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App11" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <TextBlock Text=" :" /> <MyControls:WaterMarkedTextBox WaterMark="     Enter" /> </StackPanel> </Page> 

In order not to think about connecting the namespace, I usually drag new components onto the form from the Tools panel:

Well, how it all looks, you can see in the first picture of this post, well, or by repeating my actions and running the application.

')

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


All Articles