Suggestion: WatermarkTextBox : add Click Event on DeleteButton

Jan 8, 2013 at 12:38 PM
Edited Jan 8, 2013 at 12:39 PM

Hi,

Could you add the event for the DeleteButton in WatermarkTextBox Template ?

I have implemented the solution locally, but it will be great if you can add this in your framework.

You can find the code below to include to this solution (in Red color):

In WatermarkTextBox.cs:

[TemplatePart(Name = WatermarkTextBlockName, Type = typeof(TextBlock))]
    [TemplateVisualState(GroupName = WatermarkStatesGroupName, Name = WatermarkVisibleStateName)]
    [TemplateVisualState(GroupName = WatermarkStatesGroupName, Name = WatermarkHiddenStateName)]
    public class WatermarkTextBox : TextBox
    {
        public event EventHandler OnDeleteButtonClick;

        #region Consts
        private const string WatermarkStatesGroupName = "WatermarkStates";
        private const string WatermarkVisibleStateName = "WatermarkVisible";
        private const string WatermarkHiddenStateName = "WatermarkHidden";
        private const string WatermarkTextBlockName = "WatermarkTextBlock"; 
        #endregion

        #region WatermarkText
        /// <summary>
        /// WatermarkText Dependency Property
        /// </summary>
        public static readonly DependencyProperty WatermarkTextProperty =
            DependencyProperty.Register(
                "WatermarkText",
                typeof(string),
                typeof(WatermarkTextBox),
                new PropertyMetadata("Type something..."));

        /// <summary>
        /// Gets or sets the WatermarkText property. This dependency property 
        /// indicates the watermark text to show to the user.
        /// </summary>
        public string WatermarkText
        {
            get { return (string)GetValue(WatermarkTextProperty); }
            set { SetValue(WatermarkTextProperty, value); }
        }
        #endregion

        #region WatermarkStyle
        /// <summary>
        /// WatermarkStyle Dependency Property
        /// </summary>
        public static readonly DependencyProperty WatermarkStyleProperty =
            DependencyProperty.Register(
                "WatermarkStyle",
                typeof(Style),
                typeof(WatermarkTextBox),
                new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets the WatermarkStyle property. This dependency property 
        /// indicates the style of the watermark (TextBlock).
        /// </summary>
        public Style WatermarkStyle
        {
            get { return (Style)GetValue(WatermarkStyleProperty); }
            set { SetValue(WatermarkStyleProperty, value); }
        }
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="WatermarkTextBox" /> class.
        /// </summary>
        public WatermarkTextBox()
        {
            this.Loaded += WatermarkTextBox_Loaded;

            DefaultStyleKey = typeof (WatermarkTextBox);
            this.TextChanged += OnTextChanged;
        }

        void WatermarkTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            var deleteButton = this.GetDescendantsOfType<Button>().Where(x => x.Name == "DeleteButton").SingleOrDefault();
            if (deleteButton != null)
            {
                deleteButton.Click -= deleteButton_Click;
                deleteButton.Click += deleteButton_Click;
            }
        }

        void deleteButton_Click(object sender, RoutedEventArgs e)
        {
            if (OnDeleteButtonClick != null)
                OnDeleteButtonClick(this, new EventArgs());
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            UpdateWatermarkVisualState();
        }

        private void UpdateWatermarkVisualState()
        {
            var focusedElement = FocusManager.GetFocusedElement() as DependencyObject;
            var isFocused =
                (this == focusedElement) ||
                (focusedElement != null && focusedElement.GetAncestors().Contains(this));
            UpdateWatermarkVisualState(isFocused);
        }

        private void UpdateWatermarkVisualState(bool isFocused)
        {
            if (!isFocused && string.IsNullOrEmpty(this.Text))
            {
                VisualStateManager.GoToState(this, WatermarkVisibleStateName, true);
            }
            else
            {
                VisualStateManager.GoToState(this, WatermarkHiddenStateName, true);
            }
        }

        protected override void OnGotFocus(Windows.UI.Xaml.RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            UpdateWatermarkVisualState(true);
        }

        protected override void OnLostFocus(Windows.UI.Xaml.RoutedEventArgs e)
        {
            base.OnLostFocus(e);
            UpdateWatermarkVisualState(false);
        }

        private void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            UpdateWatermarkVisualState();
        }
    }

 

Regards,

Willy Laroche

Coordinator
Jan 8, 2013 at 6:51 PM

Why would you use that instead of the TextChanged event?

Jan 9, 2013 at 8:39 AM
xyzzer wrote:

Why would you use that instead of the TextChanged event?

yes it works, but TextChanged event force to me to detect all text changes.

For example, i would like to seperate it with the true action to delete the watermark textbox content.

I think it is cleaner to separate this 2 events.

For the logic, when we use a custom control which contains a button in the template, it seems to me we could have the need to implement the button click  behavior... ?

 

Coordinator
Jan 10, 2013 at 11:38 PM

What if someone simply selects all text and deletes it though? I don't think it makes sense to only check for button clicks. Plus if someone restyled the control for example to add another button, for example to put some default values or display previously used or otherwise suggested values - it would break the functionality. You can always derive from the control and add the functionality you want yourself.