Scratching that old itch.

First of all, I must apologise that it’s been so long since I last blogged. It’s been an insanely busy time for me (and I don’t mean that I’ve been coding with my underpants on my head). As you may be aware, I’m a big fan of Blend behaviours, so I thought that I’d take the time to revisit an old favourite of mine. To that end, I present all the code you’ll need to create a watermarked textbox.

namespace Goldlight.Extensions.Behaviors
{
  using System.Windows.Interactivity;
  using System.Windows.Controls;
  using System.Windows.Media;
  using System.Windows;

  public class WatermarkTextBoxBehavior : Behavior<TextBox>
  {
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.LostFocus += new RoutedEventHandler(LostFocus);
      AssociatedObject.GotFocus += new RoutedEventHandler(GotFocus);
      SetWatermark();
    }

    protected override void OnDetaching()
    {
      base.OnDetaching();
      AssociatedObject.LostFocus -= new RoutedEventHandler(LostFocus);
      AssociatedObject.GotFocus -= new RoutedEventHandler(GotFocus);
    }
    /// <summary>
    /// Get or set the brush to use as the foreground.
    /// </summary>
    public Brush WatermarkForeground { get; set; }
    /// <summary>
    /// Get or set the brush to use as the background.
    /// </summary>
    public Brush WatermarkBackground { get; set; }
    /// <summary>
    /// Get or set the text to apply as the watermark.
    /// </summary>
    public string WatermarkText { get; set; }

    /// <summary>
    /// Reset the colours of the textbox.
    /// </summary>
    private void SetStandard()
    {
      AssociatedObject.ClearValue(TextBox.ForegroundProperty);
      AssociatedObject.ClearValue(TextBox.BackgroundProperty);

      if (AssociatedObject.Text == WatermarkText)
      {
        AssociatedObject.Text = string.Empty;
      }
    }
    /// <summary>
    /// Set the watermark colours for the textbox.
    /// </summary>
    private void SetWatermark()
    {
      if (WatermarkForeground != null)
      {
        AssociatedObject.Foreground = WatermarkForeground;
      }
      if (WatermarkBackground != null)
      {
        AssociatedObject.Background = WatermarkBackground;
      }
      AssociatedObject.Text = WatermarkText;
    }
    void GotFocus(object sender, RoutedEventArgs e)
    {
      SetStandard();
    }
    void LostFocus(object sender, RoutedEventArgs e)
    {
      CheckText(AssociatedObject.Text);
    }
    private void CheckText(string value)
    {
      if (string.IsNullOrWhiteSpace(value))
      {
        SetWatermark();
      }
      else
      {
        SetStandard();
      }
    }
  }
}

The code is pretty straightforward. When the textbox receives focus, if it contains just the Watermark text, the watermark text is cleared out and the original foreground and background brushes are restored. When the textbox loses focus, if it’s empty the watermark text is displayed and the watermark fore and background brushes are set. Now, for the clever bit, because we’re updating the textbox text directly we aren’t going to be updating any underlying binding

Leave a comment