using System.Drawing;
using System.ComponentModel;
namespace System.Windows.Forms
{
public class PlaceholderTextBox : TextBox
{
#region Fields
#region Protected Fields
protected string _placeholderText = "Default placeholder"; //The placeholder text
protected Color _placeholderColor; //Color of the placeholder when the control does not have focus
protected Color _placeholderActiveColor; //Color of the placeholder when the control has focus
#endregion
#region Private Fields
private Panel placeholderContainer; //Container to hold the placeholder
private Font placeholderFont; //Font of the placeholder
private SolidBrush placeholderBrush; //Brush for the placeholder
#endregion
#endregion
#region Constructors
public PlaceholderTextBox()
{
Initialize();
}
#endregion
#region Private Methods
///
/// Initializes placeholder properties and adds CtextBox events
///
private void Initialize()
{
//Sets some default values to the placeholder properties
_placeholderColor = Color.LightGray;
_placeholderActiveColor = Color.Gray;
placeholderFont = Font;
placeholderBrush = new SolidBrush(_placeholderActiveColor);
placeholderContainer = null;
//Draw the placeholder, so we can see it in design time
DrawPlaceholder();
//Eventhandlers which contains function calls.
//Either to draw or to remove the placeholder
Enter += new EventHandler(ThisHasFocus);
Leave += new EventHandler(ThisWasLeaved);
TextChanged += new EventHandler(ThisTextChanged);
}
///
/// Removes the placeholder if it should
///
private void RemovePlaceholder()
{
if (placeholderContainer != null)
{
Controls.Remove(placeholderContainer);
placeholderContainer = null;
}
}
///
/// Draws the placeholder if the text length is 0
///
private void DrawPlaceholder()
{
if (placeholderContainer == null && TextLength <= 0)
{
placeholderContainer = new Panel(); // Creates the new panel instance
placeholderContainer.Paint += new PaintEventHandler(placeholderContainer_Paint);
placeholderContainer.Invalidate();
placeholderContainer.Click += new EventHandler(placeholderContainer_Click);
Controls.Add(placeholderContainer); // adds the control
}
}
#endregion
#region Eventhandlers
#region Placeholder Events
private void placeholderContainer_Click(object sender, EventArgs e)
{
Focus(); //Makes sure you can click wherever you want on the control to gain focus
}
private void placeholderContainer_Paint(object sender, PaintEventArgs e)
{
//Setting the placeholder container up
placeholderContainer.Location = new Point(2, 0); // sets the location
placeholderContainer.Height = Height; // Height should be the same as its parent
placeholderContainer.Width = Width; // same goes for width and the parent
placeholderContainer.Anchor = AnchorStyles.Left | AnchorStyles.Right; // makes sure that it resizes with the parent control
if (ContainsFocus)
{
//if focused use normal color
placeholderBrush = new SolidBrush(_placeholderActiveColor);
}
else
{
//if not focused use not active color
placeholderBrush = new SolidBrush(_placeholderColor);
}
//Drawing the string into the panel
Graphics g = e.Graphics;
g.DrawString(_placeholderText, placeholderFont, placeholderBrush, new PointF(-2f, 1f));//Take a look at that point
//The reason I'm using the panel at all, is because of this feature, that it has no limits
//I started out with a label but that looked very very bad because of its paddings
}
#endregion
#region CTextBox Events
private void ThisHasFocus(object sender, EventArgs e)
{
//if focused use focus color
placeholderBrush = new SolidBrush(_placeholderActiveColor);
//The placeholder should not be drawn if the user has already written some text
if (TextLength <= 0)
{
RemovePlaceholder();
DrawPlaceholder();
}
}
private void ThisWasLeaved(object sender, EventArgs e)
{
//if the user has written something and left the control
if (TextLength > 0)
{
//Remove the placeholder
RemovePlaceholder();
}
else
{
//But if the user didn't write anything, Then redraw the control.
Invalidate();
}
}
private void ThisTextChanged(object sender, EventArgs e)
{
//If the text of the textbox is not empty
if (TextLength > 0)
{
//Remove the placeholder
RemovePlaceholder();
}
else
{
//But if the text is empty, draw the placeholder again.
DrawPlaceholder();
}
}
#region Overrided Events
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//Draw the placeholder even in design time
DrawPlaceholder();
}
protected override void OnInvalidated(InvalidateEventArgs e)
{
base.OnInvalidated(e);
//Check if there is a placeholder
if (placeholderContainer != null)
//if there is a placeholder it should also be invalidated();
placeholderContainer.Invalidate();
}
#endregion
#endregion
#endregion
#region Properties
[Category("Placeholder attribtues")]
[Description("Sets the text of the placeholder")]
public string Placeholder
{
get { return _placeholderText; }
set
{
_placeholderText = value;
Invalidate();
}
}
[Category("Placeholder attribtues")]
[Description("When the control gaines focus, this color will be used as the placeholder's forecolor")]
public Color PlaceholderActiveForeColor
{
get { return _placeholderActiveColor; }
set
{
_placeholderActiveColor = value;
Invalidate();
}
}
[Category("Placeholder attribtues")]
[Description("When the control looses focus, this color will be used as the placeholder's forecolor")]
public Color PlaceholderForeColor
{
get { return _placeholderColor; }
set
{
_placeholderColor = value;
Invalidate();
}
}
[Category("Placeholder attribtues")]
[Description("The font used on the watermark. Default is the same as the control")]
public Font PlaceholderFont
{
get
{
return placeholderFont;
}
set
{
placeholderFont = value;
Invalidate();
}
}
#endregion
}
}