WPF:数値しか受け付けないTextBox

やあ子供たち。暖かくなってきたね。冬用タイヤはもう交換したかな。今日はWPFで数値しか受け付けないテキストボックスの実装方法についてのメモだよ。「ここは数値を入力するテキストボックスなので数値以外のものは入力できないようにしてくれないか」というよくある要件に答えるためのソリューションについてのメモだよ。

今日作るプログラムはこれだけのものだ。


まずテキストボックスにデフォルトの文字列が表示されている。このままだと数値だろうがそれ以外の文字だろうが何も入力できないので、まずはこれをDelキーで削除して何か文字を打ち込もうとすると、、あら不思議。このテキストボックスには、数値しか入力できないやん!てなことになる。

●まずUIを作ろう
いつものようにVisualStudioのUIエディタでUIを作ってみよう。出来上がったXAMLに対して、以下の箇所に更新を入れよう。

そう、今回はPreviewTextInputというプロパティに対してハンドラを実装してやることがポイントだ。上記PreviewTextInputの赤字のとこで右クリックして「定義」を選んで、コードビハインドの編集画面に移動しよう。

●コードビハインド
コードビハインドのC#コードを以下に示そう。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication4
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            bool yes_parse = false;
            {
                // 既存のテキストボックス文字列に、
                // 今新規に一文字追加された時、その文字列が
                // 数値として意味があるかどうかをチェック
                {
                    float xx;
                    var tmp= textbox_1.Text + e.Text;
                    yes_parse = Single.TryParse(tmp, out xx);
                }
                // 最初の一文字の場合に限り、プラス文字とマイナス文字の
                // 入力は許可する。
                yes_parse |=
                    (textbox_1.Text.Length == 0) &&
                    (e.Text == "+") || (e.Text == "-");
            }
            // 更新したい場合は false, 更新したくない場合は true
            // を返すべし。(混乱しやすいので注意!)
            e.Handled = !yes_parse;
        }
    }
}

いかがだろうか。あまりにも短くて解りやすい内容だね。なので解説はいらないかも知れないが、いちおうしておくと、このPreviewTextInputのハンドラというものは、テキストボックスに文字が一文字入力されるたびに、その表示更新をする前に呼び出されてくるようだよ。
新規に入力された一文字は、e.Text の中に格納されている。
なので、もともとテキストボックス上にあった文字列の末尾に、新しく入力された一文字を追加したものについて、それが意味のある文字列かどうかを判定し、その結果をもって、テキストボックスの表示を更新するか否かを決めることができるようだよ。
今回は、そのように作り出した新規の文字列を、Single.TryParse()という関数を使って、これが数値として意味のある文字列かどうかをお手軽に判定しているよ。そしてこれが数値ですと判断した場合に限り、テキストボックスの表示を更新するよ。数値ではないと判定した際には表示の更新を行わないため、つまり最後の文字の入力自体が無効ということになるよ。

●動作を確認せよ!
最後に動作確認です。このように、数値として意味のある文字列かどうかを判定しながら文字を打ち込むので、数値ではなくすような入力は一切受け付けない感じだ。もちろん2個目の小数点入力は受け付けない。先頭のプラスとマイナスだけは、それ自体だけでは数値にはならないため、Single.TryParse()の判定にはかけずに、例外的に通すようにしているよ。詳しくはソースを見てほしい。


では今日はこの辺で。
チャオ!