Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use TextBox.Watermark in Silverlight 4?

While browsing MSDN documentation, you may come across this gem: TextBox.Watermark.

"Awesome! I've been wanting a built-in way to do watermarking on my text boxes! This is great, let me go ahead and set that in XAML!"

<TextBox Watermark="This is my watermark" Margin="20"></TextBox>

Unfortunately, if you run this you won’t get what you expect:

enter image description here

And the detail: enter image description here

What is this? Well, look at the MSDN documentation closely: enter image description here

That's right. It's supported in Silverlight 4, but it also says "Do not use in a Silverlight 4 application". If you do use it, you receive a System.NotImplemented exception. To verify, here is the code for the property decompiled via Reflector:

[EditorBrowsable(EditorBrowsableState.Never)]
public object Watermark
{
get
{
StubHelper.ThrowIfNotInDesignMode();
return base.GetValue(WatermarkProperty);
}
set
{
StubHelper.ThrowIfNotInDesignMode();
base.SetValue(WatermarkProperty, value);
}
}

There it is – it throws an exception any time it's not in design mode. This makes no sense right? Why would Microsoft do this?

Unfortunately I haven't found any definitive answer yet, however if I had to guess it's because Microsoft is planning on implementing a Watermark behavior on the TextBox control in a future version (perhaps v5) and wanted to effectively reserve this property so third party control creators don't subclass TextBox and create their own Watermark property. I know of at least one control vendor, ComponentOne, who has a control that inherits from TextBox and provides a Watermark property. To me, it seems this is Microsoft's way of discouraging people from using this property name on their own TextBox subclasses.

like image 918
Unknown Avatar asked Apr 03 '12 12:04

Unknown


2 Answers

Create One Class library project . Add Class File use the Following code .....After that Add The In this dll In Your Project.

public class WatermarkTextBox : TextBox 
{ 
    private bool displayWatermark = true; 
    private bool hasFocus = false; 
     public WatermarkTextBox() 
    { 
        this.GotFocus += new RoutedEventHandler(WatermarkTextBox_GotFocus); 
        this.LostFocus += new RoutedEventHandler(WatermarkTextBox_LostFocus); 
        this.TextChanged += new TextChangedEventHandler(WatermarkTextBox_TextChanged); 
        this.Unloaded += new RoutedEventHandler(WatermarkTextBox_Unloaded); 
    } 

    private void WatermarkTextBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
        if (!hasFocus && Text == "") 
        { 
            setMode(true); 
            displayWatermark = true; 
            this.Text = Watermark; 
        } 
    } 

    private void WatermarkTextBox_Unloaded(object sender, RoutedEventArgs e) 
    { 
        this.GotFocus -= WatermarkTextBox_GotFocus; 
        this.LostFocus -= WatermarkTextBox_LostFocus; 
        this.Unloaded -= WatermarkTextBox_Unloaded; 
        this.TextChanged -= WatermarkTextBox_TextChanged; 
    } 

    private void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e) 
    { 
        hasFocus = true; 
        if (displayWatermark) 
        { 
            setMode(false); 
            this.Text = ""; 
        } 
    } 
    private void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e) 
    { 
        hasFocus = false; 
        if (this.Text == "") 
        { 
            displayWatermark = true; 
            setMode(true); 
            this.Text = Watermark; 
        } 
        else 
        { 
            displayWatermark = false; 
        } 
    } 
    private void setMode(bool watermarkStyle) 
    { 
        if (watermarkStyle) 
        { 
            this.FontStyle = FontStyles.Italic; 
            this.Foreground = new SolidColorBrush(Colors.Gray); 
        } 
        else 
        { 
            this.FontStyle = FontStyles.Normal; 
            this.Foreground = new SolidColorBrush(Colors.Black); 
        } 
    } 
    public new string Watermark 
    { 
        get { return GetValue(WatermarkProperty) as string; } 
        set { SetValue(WatermarkProperty, value); } 
    } 
    public static new readonly DependencyProperty WatermarkProperty = 
        DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata(watermarkPropertyChanged)); 
    private static void watermarkPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
        WatermarkTextBox textBox = obj as WatermarkTextBox; 
        if (textBox.displayWatermark) 
        { 
            textBox.Text = e.NewValue.ToString(); 
            textBox.setMode(true); 
        } 
    } 

XAML:

  xmlns:watertext="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1"


    <watertext:WatermarkTextBox Watermark="WElcome" Margin="150,115,120,166"></watertext:WatermarkTextBox>
like image 185
mani kandan Avatar answered Sep 21 '22 03:09

mani kandan


I revised @mani kandan's solution slightly to fix design-time error if Watermark property is not set. Also added a HasValue boolean property to be able to easily check whether user has entered text in the TextBox, and lastly changed to treat all-whitespace entries as non-entries (i.e., continue to display watermark).

Revised code:

public class WatermarkTextBox : TextBox
{

    private bool displayWatermark = true;
    private bool hasFocus = false;

    public WatermarkTextBox()
    {
        this.GotFocus += new RoutedEventHandler(WatermarkTextBox_GotFocus);
        this.LostFocus += new RoutedEventHandler(WatermarkTextBox_LostFocus);
        this.TextChanged += new TextChangedEventHandler(WatermarkTextBox_TextChanged);
        this.Unloaded += new RoutedEventHandler(WatermarkTextBox_Unloaded);
    }

    private void WatermarkTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (!hasFocus && string.IsNullOrWhiteSpace(this.Text))
        {
            setMode(true);
            displayWatermark = true;
            // avoid design-time error if Watermark not specified
            this.Text = (Watermark == null ? string.Empty : Watermark);
        }
    }

    private void WatermarkTextBox_Unloaded(object sender, RoutedEventArgs e)
    {
        this.GotFocus -= WatermarkTextBox_GotFocus;
        this.LostFocus -= WatermarkTextBox_LostFocus;
        this.Unloaded -= WatermarkTextBox_Unloaded;
        this.TextChanged -= WatermarkTextBox_TextChanged;
    }

    private void WatermarkTextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        hasFocus = true;
        if (displayWatermark)
        {
            setMode(false);
            this.Text = "";
        }
    }

    private void WatermarkTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        hasFocus = false;
        if (string.IsNullOrWhiteSpace(this.Text))
        {
            displayWatermark = true;
            setMode(true);
            this.Text = (Watermark == null ? string.Empty : Watermark);
        }
        else
        {
            displayWatermark = false;
        }
    }

    private void setMode(bool watermarkStyle)
    {
        if (watermarkStyle)
        {
            this.FontStyle = FontStyles.Italic;
            this.Foreground = new SolidColorBrush(Colors.Gray);
        }
        else
        {
            this.FontStyle = FontStyles.Normal;
            this.Foreground = new SolidColorBrush(Colors.Black);
        }
    }

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

    public static new readonly DependencyProperty WatermarkProperty =
        DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox), new PropertyMetadata(watermarkPropertyChanged));
    private static void watermarkPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        WatermarkTextBox textBox = obj as WatermarkTextBox;
        if (textBox.displayWatermark)
        {
            textBox.Text =  e.NewValue.ToString();
            textBox.setMode(true);
        }
    }

    public bool HasValue
    {
        get 
        {
            // if watermark has been specified, then compare to text value to determine if text set by user,
            // otherwise check to see if empty or whitespace.
            if (this.Watermark != null)
                return this.Watermark != this.Text;
            else
                return !string.IsNullOrWhiteSpace(this.Text);
        }
    }

}
like image 31
Dave Marley Avatar answered Sep 22 '22 03:09

Dave Marley