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:
And the detail:
What is this? Well, look at the MSDN documentation closely:
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.
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>
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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With