The TextBox Watermark Behaviour

In a previous article I described how to build a Blend 3.0 Behaviour that logged details based on an event on a UIElement. This article moves a little further forward in that a TextBox element is enhanced to provide a watermark when the text is empty.

The VS2008 solution is as follows:

blog2-1

The complete code is here:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace Behaviors
{
    /// <summary>
    /// The <see cref="WatermarkBehaviour"/> class.
    /// </summary>
    public class WatermarkBehaviour : Behavior<TextBox>
    {
        public static readonly DependencyProperty BrushColorProperty;
        public static readonly DependencyProperty WatermarkTextProperty;

        private Brush newBrush;
        private Brush oldBrush;

        #region Behavior Initialization

        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
        protected override void OnAttached()
        {
            base.OnAttached();
            oldBrush = AssociatedObject.Foreground;
            newBrush = new SolidColorBrush(BrushColor);
            AssociatedObject.Loaded += AssociatedObjectLoaded;
            AssociatedObject.GotFocus += AssociatedObjectGotFocus;
            AssociatedObject.LostFocus += AssociatedObjectLostFocus;
        }

        /// <summary>
        /// Handles the Loaded event of the AssociatedObject control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
        {
            if (!AssociatedObject.Text.Equals(string.Empty))
                return;
            AssociatedObject.Foreground = newBrush;
            AssociatedObject.Text = WatermarkText;
        }

        /// <summary>
        /// Handles the LostFocus event of the AssociatedObject control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void AssociatedObjectLostFocus(object sender, RoutedEventArgs e)
        {
            if (!AssociatedObject.Text.Equals(string.Empty)) return;
            AssociatedObject.Foreground = newBrush;
            AssociatedObject.Text = WatermarkText;
        }

        /// <summary>
        /// Handles the GotFocus event of the AssociatedObject control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void AssociatedObjectGotFocus(object sender, RoutedEventArgs e)
        {
            if (!AssociatedObject.Text.Equals(WatermarkText)) return;
            AssociatedObject.Foreground = oldBrush;
            AssociatedObject.Text = string.Empty;
        }

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.Loaded -= AssociatedObjectLoaded;
            AssociatedObject.GotFocus -= AssociatedObjectGotFocus;
            AssociatedObject.LostFocus -= AssociatedObjectLostFocus;
        }

        #endregion

        /// <summary>
        /// Initializes the <see cref="WatermarkBehaviour"/> class.
        /// </summary>
        static WatermarkBehaviour()
        {
            WatermarkTextProperty =
                DependencyProperty.Register("WatermarkText", typeof (string), typeof (WatermarkBehaviour),
                                            new UIPropertyMetadata("Enter some text here"));
            BrushColorProperty =
                DependencyProperty.Register("BrushColor", typeof (Color), typeof (WatermarkBehaviour));
        }

        /// <summary>
        /// Gets or sets the color of the brush.
        /// </summary>
        /// <value>The color of the brush.</value>
        public Color BrushColor
        {
            get { return (Color) GetValue(BrushColorProperty); }
            set { SetValue(BrushColorProperty, value); }
        }

        /// <summary>
        /// Gets or sets the watermark text.
        /// </summary>
        /// <value>The watermark text.</value>
        public string WatermarkText
        {
            get { return (string) GetValue(WatermarkTextProperty); }
            set { SetValue(WatermarkTextProperty, value); }
        }
    }
}

Points to note:

  • The Loaded event is attached to enter the watermark text if the TextBox has not been initialised with text.
  • The GotFocus event is attached to check to see if watermark text needs to be displayed. If not then the text is left in place.
  • The LostFocus event is attached to check that on moving that the original text is set correctly or that the watermark text is displayed.
  • The watermark text is user defined as well as the foregrounf brush used to display the text.

Within Expression Blend 3.0 you would use the normal “drag and drop” method to attach the Behaviour.

blog2-5

Configuring the Logging Behaviour in Expression Blend is achived through the properties panel as shown below.

blog2-2

The markup within the XAML is as follows:

        <TextBox
                 Margin="122,0,8,0"
                 Grid.Column="1"
                 Grid.Row="1"
                 TextWrapping="Wrap" Background="#FFF4D18D">
            <i:Interaction.Behaviors>
                <Behaviors:WatermarkBehaviour BrushColor="#FF993232"/>
            </i:Interaction.Behaviors>
        </TextBox>

In conclusion, the Behaviour is rather simple as showwn below – first without user text
blog2-3

and now with user text.

blog2-4

Advertisements

~ by Intelligence4 on August 31, 2009.

 
%d bloggers like this: