web-dev-qa-db-ja.com

数値のみを受け入れるWPF TextBoxを作成する

特定の範囲の数値のみを受け入れるTextBoxを作成したいと思います。そのようなTextBoxを実装する最良の方法は何ですか?

TextBoxの派生と、TextPropertyの検証と強制のオーバーライドを検討しました。ただし、これを行う方法がわかりません。また、WPFコントロールの派生は一般に推奨されないことを理解しています。


編集:
private void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    int result;
    if (!validateStringAsNumber(e.Text,out result,false))
    {
        e.Handled = true;
    }
}

(validateStringAsNumberは、主にInt.TryParseを使用する私の関数です)

提案されたソリューションのいくつかはおそらくより良いですが、私が必要とするシンプルな機能のために、このソリューションは私のニーズに十分でありながら、実装するのが最も簡単で迅速です。

20
Elad

これまでに見たほとんどの実装では、 PreviewTextInput イベントを使用して正しいマスク動作を実装しています。 これ はTextBoxを継承し、 これ は添付プロパティを使用します。どちらも.Netの MaskedTextProvider を使用して正しいマスク動作を提供しますが、単純な「数値のみ」のテキストボックスが必要な場合は、このクラスは必要ありません。

8
Lars Truijens
private void txt_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    int iValue = -1;

    if (Int32.TryParse(textBox.Text, out iValue) == false)
    {
         TextChange textChange = e.Changes.ElementAt<TextChange>(0);
         int iAddedLength = textChange.AddedLength;
         int iOffset = textChange.Offset;

         textBox.Text = textBox.Text.Remove(iOffset, iAddedLength);
    }
}
5
Nanda

私の控えめな意見では、この要件を満たすための最良の方法は、キーストロークからの数字を処理でき、クリップボードからのコピーと貼り付けも処理できるため、OnTextChangedイベントのみを使用することです。以下に示す私のVBコードがこれに光を投げることができることを願っています。

Private Sub NumericBox_TextChanged(sender As Object, e As TextChangedEventArgs) Handles Me.TextChanged
  Dim Buffer As New StringBuilder
  Dim Index As Integer = Me.SelectionStart
  For Each C In Me.Text
    If Char.IsDigit(C) Then
      Buffer.Append(C)
    ElseIf Me.SelectionStart > Buffer.Length Then
      Index -= 1
    End If
  Next
  Me.Text = Buffer.ToString
  Me.SelectionStart = Index
End Sub
4
Manta

全体として最良の理由は、テキストボックスのようにオーバーライドメソッドOnKeyPressedを使用することです。以下は、静的CharメソッドIsDigitを使用したオーバーライドのコードです。

if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar)) e.Handled = true;

あなたが本当にする必要があるのはそれだけです。

0
Robert

これは私の好ましいアプローチです:

private void yearTxt_PreviewKeyDown(object sender, KeyEventArgs e)
{
  switch (e.Key)
  {
    case Key.D0:
    case Key.D1:
    case Key.D2:
    case Key.D3:
    case Key.D4:
    case Key.D5:
    case Key.D6:
    case Key.D7:
    case Key.D8:
    case Key.D9:
    case Key.NumLock:
    case Key.NumPad0:
    case Key.NumPad1:
    case Key.NumPad2:
    case Key.NumPad3:
    case Key.NumPad4:
    case Key.NumPad5:
    case Key.NumPad6:
    case Key.NumPad7:
    case Key.NumPad8:
    case Key.NumPad9:
    case Key.Back:
      break;
    default:
      e.Handled = true;
      break;
  }
}
0
Bryun