我怎么能把一些文本放入一个文本框,这将被自动删除时,用户键入的东西在它?


当前回答

我已经创建了一个简单的代码实现,它适用于WPF和Silverlight:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;

public class TextBoxWatermarked : TextBox
{
    #region [ Dependency Properties ]

    public static DependencyProperty WatermarkProperty = DependencyProperty.Register
    (
         "Watermark",
         typeof(string),
         typeof(TextBoxWatermarked),
         new PropertyMetadata(new PropertyChangedCallback(OnWatermarkChanged))
    );
    
    #endregion
    
    
    #region [ Fields ]
    
    private bool _isWatermarked;
    private Binding _textBinding;

    #endregion


    #region [ Properties ]

    protected new Brush Foreground
    {
        get { return base.Foreground; }
        set { base.Foreground = value; }
    }

    public string Watermark
    {
        get { return (string)GetValue(WatermarkProperty); }
        set { SetValue(WatermarkProperty, value); }
    }

    #endregion


    #region [ .ctor ]
    
    public TextBoxWatermarked()
    {
        Loaded += (s, ea) => ShowWatermark();
    }
    
    #endregion


    #region [ Event Handlers ]

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        base.OnGotFocus(e);
        HideWatermark();
    }
    
    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        ShowWatermark();
    }
    
    private static void OnWatermarkChanged(DependencyObject sender, DependencyPropertyChangedEventArgs ea)
    {
        var tbw = sender as TextBoxWatermarked;
        if (tbw == null) return;
        tbw.ShowWatermark();
    }

    #endregion


    #region [ Methods ]

    private void ShowWatermark()
    {
        if (string.IsNullOrEmpty(base.Text))
        {
            _isWatermarked = true;
            base.Foreground = new SolidColorBrush(Colors.Gray);
            var bindingExpression = GetBindingExpression(TextProperty);
            _textBinding = bindingExpression == null ? null : bindingExpression.ParentBinding;
            if (bindingExpression != null)
                bindingExpression.UpdateSource();
            SetBinding(TextProperty, new Binding());
            base.Text = Watermark;
        }
    }

    private void HideWatermark()
    {
        if (_isWatermarked)
        {
            _isWatermarked = false;
            ClearValue(ForegroundProperty);
            base.Text = "";
            SetBinding(TextProperty, _textBinding ?? new Binding());
        }
    }

    #endregion
}

用法:

<TextBoxWatermarked Watermark="Some text" />

其他回答

您可以为输入的文本保留一个单独的值,并且可以在“GotFocus”和“LostFocus”事件中设置文本框的“text”字段。当您获得焦点时,如果没有值,则需要清除文本框。当你失去焦点时,你会想要设置从文本框中获取“文本”值,然后将文本框的“文本”值重置为占位符(如果它是空的)。

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";
  }
}

然后,您只需确保文本框的“Text”值初始化为占位符文本。

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

您可以进一步将其提取到扩展“TextBox”类的类中,然后在整个项目中重用它。

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);
    }
  }
}

然后这个可以直接添加到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>

这个库有水印。

Nuget包

示例用法:

<TextBox adorners:Watermark.Text="Write something here" 
         adorners:Watermark.TextStyle="{StaticResource AdornerTextStyle}"
         adorners:Watermark.VisibleWhen="EmptyAndNotKeyboardFocused"/>

看看另一个简单的解决方案:

我专注于“得到专注”和“失去专注”事件。

XAML:

<Grid>
<TextBlock x:Name="DosyaİhtivaEdenDizinYansıması" Text="Hedef Dizin Belirtin" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="White" Background="Transparent" Width="500" MinWidth="300" Margin="10,0,0,0" Opacity="0.7"/>
<TextBox x:Name="DosyaİhtivaEdenDizin" CaretBrush="White" Foreground="White" Background="Transparent" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" MinHeight="40" BorderThickness="1" BorderBrush="White" Width="500" MinWidth="300" Margin="10,0,0,0" GotFocus="DosyaİhtivaEdenDizin_GotFocus" LostFocus="DosyaİhtivaEdenDizin_LostFocus"/>
</Grid>

C#:

    #region DosyaİhtivaEdenDizin
    private void DosyaİhtivaEdenDizin_GotFocus(object sender, RoutedEventArgs e)
    {
        if (DosyaİhtivaEdenDizin.Text.Length == 0)
        {
            DosyaİhtivaEdenDizinYansıması.Text = "";
        }
    }

    private void DosyaİhtivaEdenDizin_LostFocus(object sender, RoutedEventArgs e)
    {
        if (DosyaİhtivaEdenDizin.Text.Length == 0)
        {
            DosyaİhtivaEdenDizinYansıması.Text = "Hedef Dizin Belirtin";
        }
    }
    #endregion

当使用@john-myczek的代码绑定文本框时,我遇到了一些困难。由于TextBox在更新时不会引发焦点事件,水印将在新文本下面保持可见。为了解决这个问题,我简单地添加了另一个事件处理程序:

if (d is ComboBox || d is TextBox)
{
    control.GotKeyboardFocus += Control_GotKeyboardFocus;
    control.LostKeyboardFocus += Control_Loaded;

    if (d is TextBox)
        (d as TextBox).TextChanged += Control_TextChanged;
}


private static void Control_TextChanged(object sender, RoutedEventArgs e)
{
    var tb = (TextBox)sender;
    if (ShouldShowWatermark(tb))
    {
        ShowWatermark(tb);
    }
    else
    {
        RemoveWatermark(tb);
    }
}

嗨,我把这个任务变成了一个行为。你只需要在文本框中添加这样的东西

<i:Interaction.Behaviors>
         <Behaviors:TextBoxWatermarkBehavior Label="Test Watermark" LabelStyle="{StaticResource StyleWatermarkLabel}"/>
</i:Interaction.Behaviors>

你可以在这里找到我的博客文章