Focus change text for text fields in WPF

I write an application in WPF using the MVVM template and often use TextBox es. I do not want to use labels for the user to find out the user what the text field is used for, i.e. I do not want something like this:

 <TextBlock> Name: </TextBlock> <TextBox /> 

Instead, I would like the TextBox contain its own label. Statically, you would say the following:

 <TextBox>Name</TextBox> 

If the cursor is displayed in a text box, i.e. Focus TextBox , I want the description text to disappear. If the TextBox remains empty and it loses focus, the description text should be displayed again. It looks like a StackOverflow search text box or one of Firefox. (please tell me if you are not sure what I mean).

One TextBox label may change at run time, depending on, for example, a ComboBox selected item or value in my ViewModel. (As in Firefox, searching for TextBox, if you select google from the search engine menu, the TextBox will change to โ€œGoogleโ€ if you select โ€œYahooโ€ for your set of โ€œYahooโ€). So I want to be able to link the contents of the labels.

Note that I already have a binding to Text -Property TextBox .

How can I implement this behavior and make it reusable for any of my TextBox ? Code is welcome but not needed; just describe what to do.

Thanks in advance.

+4
source share
3 answers

Here is the style that I think is exactly what you are looking for, and that is pure XAML.

 <Style x:Key="WatermarkTextBox" TargetType="{x:Type TextBox}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <Grid> <Border x:Name="BorderBase" Background="White" BorderThickness="1.4,1.4,1,1" BorderBrush="Silver"> <Label x:Name="TextPrompt" Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag}" Background="{TemplateBinding Background}" Visibility="Collapsed" Focusable="False" Foreground="Silver"/> </Border> <ScrollViewer Margin="0" x:Name="PART_ContentHost" Foreground="Black"/> </Grid> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsFocused" Value="False"/> <Condition Property="Text" Value=""/> </MultiTrigger.Conditions> <Setter Property="Visibility" TargetName="TextPrompt" Value="Visible"/> </MultiTrigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="BorderBrush" TargetName="BorderBase" Value="Black"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="DimGray" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 

Using:

 <TextBox Style="{StaticResource WatermarkTextBox}" Tag="Full Name"/> 

where Tag is the help message you want to display.

You can clear this style for your own use, but the most important part is the control that hides / shows the supporting text.

It is also worth noting that there is already a DependencyObject for storing auxiliary text, so you do not need to create your own using this method.

FrameworkElement.Tag is available for storing arbitrary information about this element. Therefore, we set the Tag property:

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.tag.aspx

+7
source

You can get from TextBox and implement your behavior. TextBox offers GotFocus / LostFocus (or OnGotFocus / OnLostFocus respectively) that should help. You should also consider creating a new DepedencyProperty so that you can define the default text in xaml and associate it with other controls / resources, etc.

+1
source

Strengthen my suggestion for using a buddy.

Adorner is basically a custom-level element that appears above / around another element. For example, if you perform a check in a binding, the red frame that adorns the invalid control is the advertiser - it is not part of the control and can be applied (and applied) to all kinds of controls. See the Adorners section in WPF docs for a simple but clear example.

I thought of Adorner for several reasons. The key is that the behavior you describe may not necessarily be limited to the TextBox . You may, for example, want the ComboBox exhibit the same behavior. Adorner's implementation will give you a consistent way to implement this functionality for multiple controls (although this doesn't make sense, like CheckBox or ProgressBar ). Secondly, you donโ€™t need to do anything with a basic control that is more complicated than implementing triggers to show and hide Adorner in response to focus events. Certificates are a bit of a pain in the butt to implement, but it is worth knowing how to do it.

All that said, I like the matte answer much more than me. The only drawbacks that I see in this approach are 1) it only works with TextBox ; you need to implement a new version of the style every time you want to use the approach on another control, 2) I can just do magic thinking, but every time I ever used the Tag property in WinForms, he told me (as soon as I learned to listen) that I was building something fragile. I am not sure for sure that this is also true in WPF, but I am sure that it is.

My comment on using the bound Text property probably needs to be amplified. If you use the Text property to store a field label, then you have a number of problems that are difficult to solve. First, since this is a related property, changing its value in a TextBox will change it in the source. So, now your source needs to know a lot of information about the state of the user interface - is there any control at the moment? If the value of the Text property is Foo , does this mean that the label is Foo or is the user entering Foo ? There are probably ways you can control this, but the best way to handle this is not necessary.

(Another issue with this paradigm: what should be the behavior if the user wants the TextBox value to be an empty string?)

+1
source

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


All Articles