web-dev-qa-db-ja.com

テキストボックスに特定の文字のみを許可する

Visual C#テキストボックスで特定の文字のみを許可するにはどうすればよいですか?ユーザーは、次の文字をテキストボックスに入力できる必要があります。他のすべてはブロックする必要があります:0〜9、+、-、/、*、(、)。

この問題を調べるためにGoogleを使用しましたが、取得できる唯一の解決策は、アルファベット文字のみを許可するか、数字のみを許可するか、特定の文字を許可しないことです。私が欲しいのは、特定の文字を禁止することではなく、デフォルトで、コードに入れた文字を除くすべてを禁止することです。

16
Annoying Bot

コメント(および入力した別の回答)で述べたように、テキストボックスでkeydownまたはkeypressイベントをキャッチするイベントハンドラーを登録する必要があります。これは、TextBoxがフォーカスを失ったときにのみTextChangedが起動されるためです。

以下の正規表現を使用すると、許可する文字に一致させることができます

Regex regex = new Regex(@"[0-9+\-\/\*\(\)]");
MatchCollection matches = regex.Matches(textValue);

そしてこれは反対を行い、許可されていない文字をキャッチします

Regex regex = new Regex(@"[^0-9^+^\-^\/^\*^\(^\)]");
MatchCollection matches = regex.Matches(textValue);

誰かがテキストボックスにテキストを貼り付けることができるので、単一の一致があるとは思っていません。その場合、キャッチテキスト変更

textBox1.TextChanged += new TextChangedEventHandler(textBox1_TextChanged);
private void textBox1_TextChanged(object sender, EventArgs e)
{
    Regex regex = new Regex(@"[^0-9^+^\-^\/^\*^\(^\)]");
    MatchCollection matches = regex.Matches(textBox1.Text);
    if (matches.Count > 0) {
       //tell the user
    }
}

単一キーの押下を検証する

textBox1.KeyPress += new KeyPressEventHandler(textBox1_KeyPress);
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    // Check for a naughty character in the KeyDown event.
    if (System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), @"[^0-9^+^\-^\/^\*^\(^\)]"))
    {
        // Stop the character from being entered into the control since it is illegal.
        e.Handled = true;
    }
}
27
Paul D'Ambra

テキストボックスのKeyDownイベントにサブスクライブする必要があります。次に、このようなもの:

private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    if (!char.IsControl(e.KeyChar) 
       && !char.IsDigit(e.KeyChar) 
       && e.KeyChar != '.' && e.KeyChar != '+' && e.KeyChar != '-'
       && e.KeyChar != '(' && e.KeyChar != ')' && e.KeyChar != '*' 
       && e.KeyChar != '/')
    {
        e.Handled = true;
        return;
    }
    e.Handled=false;
    return;
}

知っておくべき重要なことは、Handledプロパティをtrueに変更した場合、キーストロークを処理しないことです。 falseに設定します。

10
Icemanind

KeyPressedイベントをインターセプトすることは、私の意見では良い解決策です。 RegExpを使用する場合は、トリガー文字(e.32よりも小さいKeyChar)に注意してください。

しかし、この方法では、ユーザーがクリップボードからテキストを貼り付けるたびに、範囲外の文字を注入することが依然として可能です。残念ながら、これを修正するための正しいクリップボードイベントが見つかりませんでした。

したがって、防水ソリューションは、TextBox.TextChangedをインターセプトすることです。しばらくの間、元の範囲外の文字が表示されることがあります。両方を実装することをお勧めします。

using System.Text.RegularExpressions;

private void Form1_Shown(object sender, EventArgs e)
{
    filterTextBoxContent(textBox1);
}


string pattern = @"[^0-9^+^\-^/^*^(^)]";

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if(e.KeyChar >= 32 && Regex.Match(e.KeyChar.ToString(), pattern).Success) { e.Handled = true; }
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    filterTextBoxContent(textBox1);
}

private bool filterTextBoxContent(TextBox textBox)
{
    string text = textBox.Text;

    MatchCollection matches = Regex.Matches(text, pattern);
    bool matched = false;

    int selectionStart = textBox.SelectionStart;
    int selectionLength = textBox.SelectionLength;

    int leftShift = 0;
    foreach (Match match in matches)
    {
        if (match.Success && match.Captures.Count > 0)
        {
            matched = true;
            Capture capture = match.Captures[0];

            int captureLength = capture.Length;
            int captureStart = capture.Index - leftShift;
            int captureEnd = captureStart + captureLength;

            int selectionEnd = selectionStart + selectionLength;

            text = text.Substring(0, captureStart) + text.Substring(captureEnd, text.Length - captureEnd);

            textBox.Text = text;

            int boundSelectionStart = selectionStart < captureStart ? -1 : (selectionStart < captureEnd ? 0 : 1);
            int boundSelectionEnd = selectionEnd < captureStart ? -1 : (selectionEnd < captureEnd ? 0 : 1);

            if (boundSelectionStart == -1)
            {
                if (boundSelectionEnd == 0)
                {
                    selectionLength -= selectionEnd - captureStart;
                }
                else if (boundSelectionEnd == 1)
                {
                    selectionLength -= captureLength;
                }
            }
            else if (boundSelectionStart == 0)
            {
                if (boundSelectionEnd == 0)
                {
                    selectionStart = captureStart;
                    selectionLength = 0;
                }
                else if (boundSelectionEnd == 1)
                {
                    selectionStart = captureStart;
                    selectionLength -= captureEnd - selectionStart;
                }
            }
            else if (boundSelectionStart == 1)
            {
                selectionStart -= captureLength;
            }

            leftShift++;
        }
    }

    textBox.SelectionStart = selectionStart;
    textBox.SelectionLength = selectionLength;

    return matched;
}
1
Martin Wantke

おそらく KeyDownイベントKeyPressイベント または KeyUpイベント を使用できます。まず、私が思うKeyDownイベントを試してみます。

イベント引数のHandledプロパティを設定して、イベントの処理を停止できます。

1
Maarten

検証イベントIMOの最も簡単な方法は、文字配列を使用してテキストボックスの文字を検証することです。 True-反復と検証は特に効率的ではありませんが、簡単です。

または、入力文字列に対してホワイトリスト文字の正規表現を使用します。あなたのイベントはここMSDNで利用可能です: http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

0
iivel