Watermark / hint text / placeholder TextBox

后端 未结 30 2554
遇见更好的自我
遇见更好的自我 2020-11-22 02:20

How can I put some text into a TextBox which is removed automatically when user types something in it?

相关标签:
30条回答
  • 2020-11-22 02:32
    <Window.Resources>
    
        <Style x:Key="TextBoxUserStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
          <Setter Property="Foreground" Value="Black"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
          <Setter Property="VerticalContentAlignment" Value="Center"/>
          <Setter Property="Width" Value="225"/>
          <Setter Property="Height" Value="25"/>
          <Setter Property="FontSize" Value="12"/>
          <Setter Property="Padding" Value="1"/>
          <Setter Property="Margin" Value="5"/>
          <Setter Property="AllowDrop" Value="true"/>
          <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type TextBox}">
                <Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
                  <Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
                    <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
                  </Border>
                </Border>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
    
        <Style x:Key="PasswordBoxVistaStyle" BasedOn="{x:Null}" TargetType="{x:Type PasswordBox}">
          <Setter Property="Foreground" Value="Black"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
          <Setter Property="VerticalContentAlignment" Value="Center"/>
          <Setter Property="Width" Value="225"/>
          <Setter Property="Height" Value="25"/>
          <Setter Property="FontSize" Value="12"/>
          <Setter Property="Padding" Value="1"/>
          <Setter Property="Margin" Value="5"/>
          <Setter Property="AllowDrop" Value="true"/>
          <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type PasswordBox}">
                <Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4">
                  <Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3">
                    <Grid>
                      <Label x:Name="lblPwd" Content="Password" FontSize="11" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Verdana" Foreground="#828385" Padding="0"/>
                      <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/>
                    </Grid>
                  </Border>
                </Border>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsFocused" Value="True">
                    <Setter Property="Visibility" TargetName="lblPwd" Value="Hidden"/>
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </Window.Resources>
    
    
            <PasswordBox Style="{StaticResource PasswordBoxVistaStyle}" Margin="169,143,22,0" Name="txtPassword" FontSize="14" TabIndex="2" Height="31" VerticalAlignment="Top" />
    

    This can help check it with your code.When applied to password box,it will show Password,which will disappear when usertypes.

    0 讨论(0)
  • 2020-11-22 02:32

    MahApps.Metro for WPF has a built-in watermark control, if you'd rather not roll your own. It's fairly straightforward to use.

     <AdornerDecorator>
                <TextBox Name="txtSomeText"
                         Width="200"
                         HorizontalAlignment="Right">
                    <Controls:TextBoxHelper.Watermark>I'm a watermark!</Controls:TextBoxHelper.Watermark>
                </TextBox>
            </AdornerDecorator>
    
    0 讨论(0)
  • 2020-11-22 02:32

    Here's my approach Is great for MVVM where I also check if the Text box has focus, you can also use a regular trigger just for the text value as well the point is I just change the background Image when value changes:

                        <TextBox.Style>
                            <Style TargetType="TextBox">
    
                                <Style.Triggers>
                                    <MultiTrigger>
                                        <MultiTrigger.Conditions>
                                            <Condition Property="IsFocused" Value="True"/>
                                            <Condition Property="Text" Value=""/>
                                        </MultiTrigger.Conditions>
                                        <MultiTrigger.Setters>
                                            <Setter Property="Background">
                                                <Setter.Value>
                                                    <ImageBrush ImageSource="/Images/Scan.PNG" Stretch="Uniform" AlignmentX="Left"/>
                                                </Setter.Value>
                                            </Setter>
                                        </MultiTrigger.Setters>
                                    </MultiTrigger>
    
                                </Style.Triggers>
                            </Style>
                        </TextBox.Style>
                    </TextBox>
    
    0 讨论(0)
  • 2020-11-22 02:33

    This is a sample which demonstrates how to create a watermark textbox in WPF:

    <Window x:Class="WaterMarkTextBoxDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WaterMarkTextBoxDemo"
        Height="200" Width="400">
    
        <Window.Resources>
    
            <SolidColorBrush x:Key="brushWatermarkBackground" Color="White" />
            <SolidColorBrush x:Key="brushWatermarkForeground" Color="LightSteelBlue" />
            <SolidColorBrush x:Key="brushWatermarkBorder" Color="Indigo" />
    
            <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
            <local:TextInputToVisibilityConverter x:Key="TextInputToVisibilityConverter" />
    
            <Style x:Key="EntryFieldStyle" TargetType="Grid" >
                <Setter Property="HorizontalAlignment" Value="Stretch" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Margin" Value="20,0" />
            </Style>
    
        </Window.Resources>
    
    
        <Grid Background="LightBlue">
    
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
    
            <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>
    
            <Grid Grid.Row="1" Background="{StaticResource brushWatermarkBackground}" Style="{StaticResource EntryFieldStyle}" >
                <TextBlock Margin="5,2" Text="This dissappears as the control gets focus..." Foreground="{StaticResource brushWatermarkForeground}" >
                    <TextBlock.Visibility>
                        <MultiBinding Converter="{StaticResource TextInputToVisibilityConverter}">
                            <Binding ElementName="txtUserEntry2" Path="Text.IsEmpty" />
                            <Binding ElementName="txtUserEntry2" Path="IsFocused" />
                        </MultiBinding>
                    </TextBlock.Visibility>
                </TextBlock>
                <TextBox Name="txtUserEntry2" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" />
            </Grid>
    
        </Grid>
    
    </Window>
    

    TextInputToVisibilityConverter is defined as:

    using System;
    using System.Windows.Data;
    using System.Windows;
    
    namespace WaterMarkTextBoxDemo
    {
        public class TextInputToVisibilityConverter : IMultiValueConverter
        {
            public object Convert( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture )
            {
                // Always test MultiValueConverter inputs for non-null
                // (to avoid crash bugs for views in the designer)
                if (values[0] is bool && values[1] is bool)
                {
                    bool hasText = !(bool)values[0];
                    bool hasFocus = (bool)values[1];
    
                    if (hasFocus || hasText)
                        return Visibility.Collapsed;
                }
    
                return Visibility.Visible;
            }
    
    
            public object[] ConvertBack( object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture )
            {
                throw new NotImplementedException();
            }
        }
    }
    

    Note: This is not my code. I found it here, but I think this is the best approach.

    0 讨论(0)
  • 2020-11-22 02:33

    You can keep a seperate value for the entered text and you can set it along with the "Text" field of the text box in the "GotFocus" and "LostFocus" events. When you get the focus, you'll want to clear the text box if there is no value. And when you loss the focus, you'll want to set the get the "Text" value from the text box and then reset the "Text" value of the text box to the place holder if it is empty.

    private String username = "";
    
    private void usernameTextBox_GotFocus(object sender, RoutedEventArgs e) {
      if (String.IsNullOrEmpty(username)) {
        usernameTextBox.Text = "";
      }
    }
    
    private void usernameTextBox_LostFocus(object sender, RoutedEventArgs e) {
      username = usernameTextBox.Text;
      if (String.IsNullOrEmpty(usernameTextBox.Text)) {
        usernameTextBox.Text = "Username";
      }
    }
    

    Then you just have to make sure that the "Text" value of the text box is initialized to the place holder text.

    <TextBox x:Name="usernameTextBox" Text="Username" GotFocus="usernameTextBox_GotFocus" LostFocus="usernameTextBox_LostFocus" />
    

    You can further extract this into a class that extends the "TextBox" class and then reuse it through out your project.

    namespace UI {
      public class PlaceholderTextBox : TextBox {
        public String Value { get; set; }
        public String PlaceholderText { get; set; }
        public Brush PlaceholderBrush { get; set; }
        private Brush ValuedBrush { get; set; }
    
        public PlaceholderTextBox() : base() {}
    
        protected override void OnInitialized(EventArgs e) {
          base.OnInitialized(e);
    
          ValuedBrush = this.Foreground;
    
          if (String.IsNullOrEmpty(this.Text)) {
            this.Text = PlaceholderText;
            this.Foreground = PlaceholderBrush;
          }
        }
    
        protected override void OnGotFocus(System.Windows.RoutedEventArgs e) {
          this.Foreground = ValuedBrush;
          if (String.IsNullOrEmpty(Value)) {
            this.Text = "";
          }
    
          base.OnGotFocus(e);
        }
    
        protected override void OnLostFocus(System.Windows.RoutedEventArgs e) {
          Value = this.Text;
          if (String.IsNullOrEmpty(this.Text)) {
            this.Text = PlaceholderText;
            this.Foreground = PlaceholderBrush;
          }
    
          base.OnLostFocus(e);
        }
      }
    }
    

    And then this can be added in the directly in the xaml.

    <Window x:Class="UI.LoginWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:m="clr-namespace:UI"
            Initialized="Window_Initialized">
        <Grid>
            <m:PlaceholderTextBox x:Name="usernameTextBox" PlaceholderText="Username" PlaceholderBrush="Gray" />
        </Grid>
    </Window>
    
    0 讨论(0)
  • 2020-11-22 02:35

    Here is the simplest solution:

                <Grid>
                    <Label Content="Placeholder text" VerticalAlignment="Center" Margin="10">
                        <Label.Style>
                            <Style TargetType="Label">
                                <Setter Property="Foreground" Value="Transparent"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Expression}" Value="">
                                        <Setter Property="Foreground" Value="Gray"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Label.Style>
                    </Label>
                    <TextBox HorizontalAlignment="Stretch" Margin="5" Background="Transparent"
                     Text="{Binding Expression, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Padding="5">
                    </TextBox>
            </Grid>
    

    This is a textbox with transparent backgound overlaying a label. The label's gray text is turned transparent by a data trigger that fires whenever the bound text is something other than empty string.

    0 讨论(0)
提交回复
热议问题