Well, I love mucking around in code and I recently decided to see how easy it would be to knock together a user control that would work in both WPF and Silverlight. If you keep it simple, it is really really easy to do. To this end, I present to you the WatermarkTextbox.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
{
public class WatermarkTextBox : TextBox, INotifyPropertyChanged
{
public WatermarkTextBox()
{
ApplyWatermark();
}
protected virtual void Changed(string propertyName)
{
ApplyWatermark();
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _watermarkText = “Watermark”;
public string WatermarkText
{
get
{
return _watermarkText;
}
set
{
if (_watermarkText != value)
{
if (string.IsNullOrEmpty(Text) || Text == _watermarkText)
{
Text = value;
}
_watermarkText = value;
Changed(“WatermarkText”
}
}
}
private System.Windows.Media.Brush _watermarkForeground = new SolidColorBrush(Colors.LightGray);
public System.Windows.Media.Brush WatermarkForeground
{
get
{
return _watermarkForeground;
}
set
{
if (_watermarkForeground != value)
{
_watermarkForeground = value;
Changed(“WatermarkForeground”
}
}
}
private System.Windows.Media.Brush _watermarkBackground = new SolidColorBrush(Colors.Yellow);
public System.Windows.Media.Brush WatermarkBackground
{
get
{
return _watermarkBackground;
}
set
{
if (_watermarkBackground != value)
{
_watermarkBackground = value;
Changed(“WatermarkBackground”
}
}
}
private System.Windows.Media.Brush _standardForeground = new SolidColorBrush(Colors.Black);
public System.Windows.Media.Brush StandardForeground
{
get
{
return _standardForeground;
}
set
{
if (_standardForeground != value)
{
_standardForeground = value;
Changed(“StandardForeground”
}
}
}
private System.Windows.Media.Brush _standardBackground = new SolidColorBrush(Colors.White);
public System.Windows.Media.Brush StandardBackground
{
get
{
return _standardBackground;
}
set
{
if (_standardBackground != value)
{
_standardBackground = value;
Changed(“StandardBackground”);
}
}
private void
{
Foreground = StandardForeground;
Background = StandardBackground;
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (Text == WatermarkText)
{
Text = string.Empty;
SetStandard();
}
base
}
protected override void OnLostFocus(RoutedEventArgs e)
{
Text = Text.Trim();
if (Text.Length == 0)
{
ApplyWatermark();
}
base
}
private void ApplyWatermark()
{
if (string.IsNullOrEmpty(Text) || Text == WatermarkText)
{
Text = WatermarkText;
Foreground = WatermarkForeground;
Background = WatermarkBackground;
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
Please feel free to use this class as you like. It comes with no warranty because it’s intended as a proof of concept only. It can do with a tidy up, and it should use Coerce values but I leave that for you to do.
Thanks so much! This was very helpful!
Thanks Monica. I’m glad it helped.
Thanks a lot! It is the best way of watermarkin a control if someone need to have a standard control behavour without retemplating it.
Thanks Pete, helpful indeed.
One question though…Why did you opt to implement INotofyPropertyChanged instead of using dependency properties (for WatermarkText,WatermarkBackrgound…etc)?
Stefan, I use INPC a lot – it’s just a much lighter way of notifying that things have changed. It’s just a personal preference, as I use it a lot in MVVM. I’m glad this has helped.