以下のようなテキストボックス (Name: SampleTextBox) があるとして、このテキストボックスには数字しか入力できないようにするとします。
仮に数字以外が入力された場合、このテキストボックスに再度フォーカスが当たって入力可能になるようにするにはどうすれば良いか? というのが今回の内容です。
その1:Focus メソッドを使う
フォーカスを当てることのできる (選択可能な) コントロールには Focus
メソッドが組み込まれています。
SampleTextBox に入力された内容が適切かどうかを条件式で判定して、もし不適切であれば Focus
メソッドで再度フォーカスを当てる、という方法です。
using System.Text.RegularExpressions;
if (!Regex.IsMatch(SampleTextBox.Text, @"^[0-9]*$")) // 入力された内容がすべて数字かどうか判定
{
MessageBox.Show("数字以外が入力されています");
SampleTextBox.Focus()
}
簡単な方法なので初心者のうちはついつい多用してしまいがちですが、フォームのロード時には Focus
メソッドは使えないので注意が必要です。
また、公式ドキュメントには Focus
メソッドが使えないコントロールが挙げられています。
次の一覧のWindows フォーム コントロールは選択できません。 これらのコントロールから派生したコントロールも選択できません。
Panel
GroupBox
PictureBox
ProgressBar
Splitter
Label
LinkLabel (コントロールにリンクがない場合)
その2:テキストボックスをアクティブにする
「テキストボックスにフォーカスを当てる」ということは、厳密にはテキストボックスをアクティブにすることに他なりません。なので、入力内容が不適切であると判定した際に、テキストボックスをアクティブにしてやると良さそうです。
コントロールに組み込まれている Select
メソッドをつかって、テキストボックスをアクティブにすることができます。
using System.Text.RegularExpressions;
if (!Regex.IsMatch(SampleTextBox.Text, @"^[0-9]*$")) // 入力された内容がすべて数字かどうか判定
{
MessageBox.Show("数字以外が入力されています");
SampleTextBox.Select()
}
Focus
メソッドとほぼ変わりません。
Select
メソッドで使えないコントロールも公式ドキュメントに記載されていますが、こちらも Focus
メソッドと同じでした。
Select メソッドと Focus メソッドの違い
戻り値
公式ドキュメントによると、Select
メソッドの定義は以下の通りです。
コントロールをアクティブにします。
C#public void Select ();
Focus
メソッドの定義は以下の通りです。
コントロールをアクティブにします。
C#public bool Focus ();
Focus
メソッドには bool
型の戻り値が設定されています。Select
メソッドはコントロールに正常にフォーカスを当てることができても特に何か返すわけではないが、Focus
の場合はフォーカスを当てることができたら true
、できなければ false
を返してくれるみたいです。
フォームのロード時に使えるかどうか
一方、Select
メソッドはフォームのロード時に使うことができます。
public class SampleForm: Form
{
public void SampleForm_Load(object sender, EventArgs e)
{
SampleTextBox.Focus(); // 機能しない
SampleTextBox.Select(); // フォーカスが当たる
this.ActiveControl = SampleTextBox; // フォーカスが当たる
}
}
本題とは少しずれますが、フォームが開いた際に最初からフォーカスが当たっている状態にしたい、といったときに便利です。
また、親であるフォームの ActiveControl
プロパティにテキストボックスをセットすることでも、テキストボックスをアクティブにすることができます (ActiveControl
プロパティと Select
メソッドはほぼ同じ動きをします)。
その3:テキストボックスの Validating イベントを使う
テキストボックスには Validating
イベントを追加できます。これはテキストボックスなどのコントロールから別のコントロールに移る際に呼び出されるイベントで、呼び出された際にイベントとしてセットされたメソッドの処理が実行されます。
上記の Validating
という項目をダブルクリックすると、対応するメソッドが自動で生成されます。とても便利。
再度テキストボックスにフォーカスを与える処理は以下のようになります。
SampleTextBox_Validating(object sender, CancelEventArgs e)
{
Textox tb = (TextBox)sender;
if (!Regex.IsMatch(tb.Text, @"^[0-9]*$")) // 入力された内容がすべて数字かどうか判定
{
e.Cancel = true;
}
}
Validating
イベントではメソッドに CancelEventArgs
型の値が渡されます。この値の Cancel
プロパティを true
にしてあげると、別コントロールへのフォーカス遷移をキャンセルしてくれます。
つまり、テキストボックスに数字以外の文字が入力されていた場合、送信ボタンを押したとしても内容が送信されず、送信ボタンを押す前の状態 (テキストボックスの入力待ち状態) に戻る、というわけです。ジョジョのGERみたい。
ただし、こいつにも弱点があります。それは、「遷移先の CausesValidation
プロパティが false
なら、遷移元の Validating
イベントは無視される」という点です。
テキストボックスが入力待ちであっても他のボタンを押したい、というときに CausesValidation
プロパティは役に立つのですが、送信ボタンなど「テキストボックスの中身が正しくないと選択しちゃダメ」みたいなコントロールの CausesValidation
プロパティは極力いじらないのが良さそうです。
参考
CausesValidation
プロパティを使った一例を取り扱っています。