RunningCSharp

MS系開発者による、雑多な記事。記事は所属企業とは関係のない、個人の見解です。

WPF:テキストボックスへの入力制限

textBoxのTextChangedイベントより禁止文字の検知と削除を行う例を記載します。(『あ~お』の文字列を禁止する)

2016/05/17 初回入力制約はPreviewTextInputで行い、元に戻す・やり直し処理のみTextChangedイベントで行わないと、 IME入力中に禁止文字が来ると編集が止まってしまう問題や元に戻す・やり直しに不備が出たため修正しました。

private string CheckString = "あいうえお";

private bool CheckText(string text)
{
    bool isFindCheckString = false;
    foreach (char c in CheckString)
    {
        //不正文字の混在を判定
        isFindCheckString |= text.Contains(c.ToString());
    }
    return !isFindCheckString;
}

private void RemoveText(TextBox textBox)
{
    //CaretIndex保存
    int caretIndex = textBox.CaretIndex;
    //置換前のテキスト長を保持(キャレット位置復元に使用)
    int textLength = textBox.Text.Length;
    foreach (char c in CheckString)
    {
        textBox.Text = textBox.Text.Replace(c.ToString(), string.Empty);
    }
    //CaretIndex格納
    textBox.CaretIndex = caretIndex - (textLength - textBox.Text.Length);

}

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    if (!CheckText(textBox.Text))
    {
        if (e.UndoAction == UndoAction.Undo || e.UndoAction == UndoAction.Redo)
        {
            //CaretIndex保存
            int caretIndex = textBox.CaretIndex;
            //置換前のテキスト長を保持(キャレット位置復元に使用)
            int textLength = textBox.Text.Length;
            if (e.UndoAction == UndoAction.Undo)
            {
                //元に戻す操作時に対象文字が含まれていたら再度「元に戻す」を実施
                textBox.Undo();
            }
            else if (e.UndoAction == UndoAction.Redo)
            {
                //やり直し操作時に対象文字が含まれていたら再度「やり直し」を実施
                textBox.Redo();
            }

            int difference = textLength - textBox.Text.Length;
            int newCaretIndex = caretIndex - difference;
            if (newCaretIndex <= textBox.Text.Length)
            {
                textBox.CaretIndex = newCaretIndex;
            }
        }
    }
}

private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    TextBox textBox = sender as TextBox;
    if (!CheckText(textBox.Text))
    {
        //書き込み処理を中断(既にTextプロパティは書き換わっているのだが、これを行わないとコードによる編集が無効になる)
        e.Handled = true;
        RemoveText(textBox);
    }
}