ユーザーがTextBox
にテキストを入力するまで「ここに入力...」を表示することは、最近ではよく知られているユーザビリティ機能です。この機能をC#でどのように実装しますか?
私のアイデアはOnTextChanged
をオーバーライドすることですが、「Type here」との間でテキストの変更を処理するロジックは少し難しいです...
初期化時に「Type here」を表示し、最初の入力で削除するのは簡単ですが、入力したテキストが空になるたびにメッセージを表示したいと思います。
探しているのは、「watermark」の付いたTextBoxです。
C# here のサンプル実装があります。すべてのクレジットはWael Alghoolにあります。
彼のコードの関連部分は次のとおりです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace wmgCMS
{
class WaterMarkTextBox : TextBox
{
private Font oldFont = null;
private Boolean waterMarkTextEnabled = false;
#region Attributes
private Color _waterMarkColor = Color.Gray;
public Color WaterMarkColor
{
get { return _waterMarkColor; }
set { _waterMarkColor = value; Invalidate();/*thanks to Bernhard Elbl
for Invalidate()*/ }
}
private string _waterMarkText = "Water Mark";
public string WaterMarkText
{
get { return _waterMarkText; }
set { _waterMarkText = value; Invalidate(); }
}
#endregion
//Default constructor
public WaterMarkTextBox()
{
JoinEvents(true);
}
//Override OnCreateControl ... thanks to "lpgray .. codeproject guy"
protected override void OnCreateControl()
{
base.OnCreateControl();
WaterMark_Toggel(null, null);
}
//Override OnPaint
protected override void OnPaint(PaintEventArgs args)
{
// Use the same font that was defined in base class
System.Drawing.Font drawFont = new System.Drawing.Font(Font.FontFamily,
Font.Size, Font.Style, Font.Unit);
//Create new brush with gray color or
SolidBrush drawBrush = new SolidBrush(WaterMarkColor);//use Water mark color
//Draw Text or WaterMark
args.Graphics.DrawString((waterMarkTextEnabled ? WaterMarkText : Text),
drawFont, drawBrush, new PointF(0.0F, 0.0F));
base.OnPaint(args);
}
private void JoinEvents(Boolean join)
{
if (join)
{
this.TextChanged += new System.EventHandler(this.WaterMark_Toggel);
this.LostFocus += new System.EventHandler(this.WaterMark_Toggel);
this.FontChanged += new System.EventHandler(this.WaterMark_FontChanged);
//No one of the above events will start immeddiatlly
//TextBox control still in constructing, so,
//Font object (for example) couldn't be catched from within
//WaterMark_Toggle
//So, call WaterMark_Toggel through OnCreateControl after TextBox
//is totally created
//No doupt, it will be only one time call
//Old solution uses Timer.Tick event to check Create property
}
}
private void WaterMark_Toggel(object sender, EventArgs args )
{
if (this.Text.Length <= 0)
EnableWaterMark();
else
DisbaleWaterMark();
}
private void EnableWaterMark()
{
//Save current font until returning the UserPaint style to false (NOTE:
//It is a try and error advice)
oldFont = new System.Drawing.Font(Font.FontFamily, Font.Size, Font.Style,
Font.Unit);
//Enable OnPaint event handler
this.SetStyle(ControlStyles.UserPaint, true);
this.waterMarkTextEnabled = true;
//Triger OnPaint immediatly
Refresh();
}
private void DisbaleWaterMark()
{
//Disbale OnPaint event handler
this.waterMarkTextEnabled = false;
this.SetStyle(ControlStyles.UserPaint, false);
//Return back oldFont if existed
if(oldFont != null)
this.Font = new System.Drawing.Font(oldFont.FontFamily, oldFont.Size,
oldFont.Style, oldFont.Unit);
}
private void WaterMark_FontChanged(object sender, EventArgs args)
{
if (waterMarkTextEnabled)
{
oldFont = new System.Drawing.Font(Font.FontFamily,Font.Size,Font.Style,
Font.Unit);
Refresh();
}
}
}
}
私のために働いたもの:
this.waterMarkActive = true;
this.textBox.ForeColor = Color.Gray;
this.textBox.Text = "Type here";
this.textBox.GotFocus += (source, e) =>
{
if (this.waterMarkActive)
{
this.waterMarkActive = false;
this.textBox.Text = "";
this.textBox.ForeColor = Color.Black;
}
};
this.textBox.LostFocus += (source, e) =>
{
if (!this.waterMarkActive && string.IsNullOrEmpty(this.textBox.Text))
{
this.waterMarkActive = true;
this.textBox.Text = "Type here";
this.textBox.ForeColor = Color.Gray;
}
};
どこbool waterMarkActive
はクラスメンバー変数であり、textBox
はTextBox
です。ただし、これはおそらくカプセル化する必要があります。
最近、Windowsがテキストボックスでウォーターマークをサポートしていることを発見しました。キューバナーと呼ばれます( here を参照)。実装は非常に簡単です。
// Within your class or scoped in a more appropriate location:
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
// In your constructor or somewhere more suitable:
SendMessage(textBox.Handle, 0x1501, 1, "Please type here.");
textBox
はTextBox
のインスタンス、0x1501
はWindowsメッセージのコードですEM_SETCUEBANNER
、wParam
はTRUE
(ゼロ以外)またはFALSE
(ゼロ)のいずれかであり、lParam
は希望するウォーターマークです表示する。 wParam
は、キューバナーをいつ表示するかを示します。 TRUE
に設定すると、コントロールにフォーカスがある場合でもキューバナーが表示されます。
@Poovenの回答に基づいて(ありがとう!)、このクラスを作成しました。私のために働く。
/// <summary>
/// A textbox that supports a watermak hint.
/// </summary>
public class WatermarkTextBox : TextBox
{
/// <summary>
/// The text that will be presented as the watermak hint
/// </summary>
private string _watermarkText = "Type here";
/// <summary>
/// Gets or Sets the text that will be presented as the watermak hint
/// </summary>
public string WatermarkText
{
get { return _watermarkText; }
set { _watermarkText = value; }
}
/// <summary>
/// Whether watermark effect is enabled or not
/// </summary>
private bool _watermarkActive = true;
/// <summary>
/// Gets or Sets whether watermark effect is enabled or not
/// </summary>
public bool WatermarkActive
{
get { return _watermarkActive; }
set { _watermarkActive = value; }
}
/// <summary>
/// Create a new TextBox that supports watermak hint
/// </summary>
public WatermarkTextBox()
{
this._watermarkActive = true;
this.Text = _watermarkText;
this.ForeColor = Color.Gray;
GotFocus += (source, e) =>
{
RemoveWatermak();
};
LostFocus += (source, e) =>
{
ApplyWatermark();
};
}
/// <summary>
/// Remove watermark from the textbox
/// </summary>
public void RemoveWatermak()
{
if (this._watermarkActive)
{
this._watermarkActive = false;
this.Text = "";
this.ForeColor = Color.Black;
}
}
/// <summary>
/// Applywatermak immediately
/// </summary>
public void ApplyWatermark()
{
if (!this._watermarkActive && string.IsNullOrEmpty(this.Text)
|| ForeColor == Color.Gray )
{
this._watermarkActive = true;
this.Text = _watermarkText;
this.ForeColor = Color.Gray;
}
}
/// <summary>
/// Apply watermak to the textbox.
/// </summary>
/// <param name="newText">Text to apply</param>
public void ApplyWatermark(string newText)
{
WatermarkText = newText;
ApplyWatermark();
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
const int EM_SETCUEBANNER = 0x1501;
public Form1()
{
InitializeComponent();
SendMessage(textBox1.Handle, EM_SETCUEBANNER, 1, "Username");
SendMessage(textBox2.Handle, EM_SETCUEBANNER, 1, "Password");
}
私は今学期にC#を学び始めたばかりなので、私は専門家ではありませんが、これは私のために働きました:(これはWindowsフォームを使用しています)
private void Form1_Load(object sender, EventArgs e)
{
textBox1.SelectionStart = 0; //This keeps the text
textBox1.SelectionLength = 0; //from being highlighted
textBox1.ForeColor = Color.Gray;
}
private void textBox_MouseMove(object sender, MouseEventArgs e)
{
Cursor.Current = Cursors.IBeam; //Without this the mouse pointer shows busy
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (textBox1.Text.Equals("Type here...") == true)
{
textBox1.Text = "";
textBox1.ForeColor = Color.Black;
}
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (textBox1.Text.Equals(null) == true || textBox1.Text.Equals("") == true)
{
textBox1.Text = "Type here...";
textBox1.ForeColor = Color.Gray;
}
}
失われたフォーカスイベントを処理し、プロパティTextが空の場合、デフォルトの文字列を入力します。
Ahmed Soliman Flashaの回答に基づいて、次のクラスを使用します。
public class TextBoxHint : TextBox
{
string _hint;
[Localizable(true)]
public string Hint
{
get { return _hint; }
set { _hint = value; OnHintChanged(); }
}
protected virtual void OnHintChanged()
{
SendMessage(this.Handle, EM_SETCUEBANNER, 1, _hint);
}
const int EM_SETCUEBANNER = 0x1501;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)]string lParam);
}
これが(winformsとは対照的に)ASP.NETの場合、これを行うことができます。
JQueryを使用している場合、これをドキュメントに追加します(または、ページを初期化します)。
var $textbox = $("textbox selector"); // assumes you select a single text box
if ($textbox.val() == "") {
$textbox.val("Type here to...");
$textbox.one('focus', function() {
$(this).attr('value', '');
});
}
複数のテキストボックスを選択する場合は、いくつかの小さなリファクタリングを行う必要があります(要素のそれぞれの内部にifステートメントを配置します)。
C#の最後のバージョンでは、TextBoxにはPlaceholderTextプロパティがあり、すべて機能します。したがって、このプロパティの値として「Type here ...」を設定するだけです。
@Joelの回答に基づきます。私は彼のクラスを修正しました(ベースに感謝します!)
/// <summary>
/// A textbox that supports a watermak hint.
/// Based on: https://stackoverflow.com/a/15232752
/// </summary>
public class WatermarkTextBox : TextBox
{
/// <summary>
/// The text that will be presented as the watermak hint
/// </summary>
private string _watermarkText;
/// <summary>
/// Gets or Sets the text that will be presented as the watermak hint
/// </summary>
public string WatermarkText
{
get { return _watermarkText; }
set { _watermarkText = value; }
}
/// <summary>
/// Whether watermark effect is enabled or not
/// </summary>
private bool _watermarkActive;
/// <summary>
/// Gets or Sets whether watermark effect is enabled or not
/// </summary>
public bool WatermarkActive
{
get { return _watermarkActive; }
set { _watermarkActive = value; }
}
/// <summary>
/// Create a new TextBox that supports watermak hint
/// </summary>
public WatermarkTextBox()
{
this.WatermarkActive = _watermarkActive;
this.Text = _watermarkText;
}
protected override void OnCreateControl()
{
base.OnCreateControl();
if (this.WatermarkActive)
CheckWatermark();
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
CheckWatermark();
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
CheckWatermark();
}
public void CheckWatermark()
{
if ((this.WatermarkActive) && String.IsNullOrWhiteSpace(this.Text))
{
ForeColor = Color.Gray;
this.Text = _watermarkText;
}
else if ((this.WatermarkActive) && (!String.IsNullOrWhiteSpace(this.Text)))
{
if (this.Text == _watermarkText)
this.Text = "";
ForeColor = Color.Black;
}
else
ForeColor = Color.Black;
}
}
空になるまで、テキストボックスの背景に「ここに入力」という文字列を描画できます
ユーザーがTextBoxにテキストを入力するまで「ここに入力...」を表示することは、最近ではよく知られているユーザビリティ機能です。この機能をC#でどのように実装しますか?
「ここに入力して...」としてtextbox.textを設定します
box_click()などのイベントを作成します
->このコードをメソッドに追加します
private void box_Click(object sender, EventArgs e)
{
Textbox b = (Textbox)sender;
b.Text = null;
}
このメソッドをテキストボックスの「Enter」イベントに割り当てます(1つまたは複数)
これがASP.NET用の場合、 TextBoxWatermark を試すことができます。
これがWindows Formsの場合、これはすでに here SOで回答されています。
HTMLウォーターマークへの同様の出力を生成
テキストボックスの「透かし」または「プレビュー」テキストのコードを次に示します。 Windowsフォームアプリケーションの使用。
[〜#〜] note [〜#〜]:この例には3つのテキストボックスがあり、それぞれに「mouse leave」イベントと「mouse enter」イベント用の以下のメソッドがあります。
private void textBoxFav_Leave(object sender, EventArgs e) {
TextBox textbox = (TextBox)sender;
if (String.IsNullOrWhiteSpace(textbox.Text)) {
textbox.ForeColor = Color.Gray;
if (textbox.Name == "textBoxFavFood") {
textbox.Text = "Favorite Food";
}
else if (textbox.Name == "textBoxFavDrink") {
textbox.Text = "Favorite Drink";
}
else if (textbox.Name == "textBoxFavDesert") {
textbox.Text = "Favorite Desert";
}
}
else {
textbox.ForeColor = Color.Black;
}
}
private void textBoxFav_Enter(object sender, EventArgs e) {
TextBox textbox = (TextBox)sender;
if (textbox.Text == "Favorite Food" || textbox.Text == "Favorite Drink" || textbox.Text == "Favorite Desert") {
textbox.Text = "";
textbox.ForeColor = Color.Black;
}
}
OnTextChangedを使用する理由TextBoxがフォーカスを取得したら、「Type here」というテキストを削除することをお勧めします。コントロールがフォーカスを失い、テキストが入力されていない場合、テキストを再度表示できます。
同じ結果で、トリッキーなロジックは不要です。
コントロールのサイズ変更の問題やデータバインディングの問題を回避し、コードをよりシンプルにしたい場合は(わかりました、疑わしいです)、ラベルを使用して表示を切り替えることができます。それから
private void FilterComboBox_GotFocus(object sender, EventArgs e)
{
FilterWatermarkLabel.Visible = false;
}
private void FilterComboBox_LostFocus(object sender, EventArgs e)
{
if (!FilterWatermarkLabel.Visible && string.IsNullOrEmpty(FilterComboBox.Text))
{
FilterWatermarkLabel.Visible = true;
}
}
画像の別のアプローチおよびデータバインディングの問題の回避もここにあります https://msdn.Microsoft.com/en-us/library/bb613590(v = vs.100).aspx