web-dev-qa-db-fra.com

Créer une zone de texte WPF qui accepte uniquement des nombres

Je voudrais créer une zone de texte qui accepte uniquement des valeurs numériques, dans une plage spécifique . Quel est le meilleur moyen d'implémenter une telle zone de texte?

J'ai pensé à dériver TextBox et à passer outre à la validation et à la contrainte de TextProperty. Cependant, je ne suis pas sûr de savoir comment procéder, et je comprends que dériver le contrôle de WPF n’est généralement pas recommandé .


Modifier:
Ce dont j'avais besoin était une zone de texte très basique qui filtre toutes les pressions sur des touches autres que des chiffres .. Le moyen le plus simple de le réaliser est de gérer l'événement TextBox.PreviewTextInput:

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

(validateStringAsNumber est ma fonction qui utilise principalement Int.TryParse)

Certaines des solutions suggérées sont probablement meilleures, mais pour la simple fonctionnalité dont j'avais besoin, cette solution est la plus simple et la plus rapide à mettre en œuvre, mais suffisante pour répondre à mes besoins.

20
Elad

La plupart des implémentations que j'ai vues jusqu'à présent utilisent l'événement PreviewTextInput pour implémenter le comportement de masque correct. Celui-ci hérite de TextBox et celui-ci utilise les propriétés attachées. Les deux utilisent. MaskedTextProvider de .Net pour fournir le comportement de masque correct, mais si vous voulez juste une simple zone de texte contenant uniquement des chiffres, vous n'avez pas besoin de cette classe.

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

À mon humble avis, le meilleur moyen de satisfaire cette exigence consiste à utiliser uniquement l'événement OnTextChanged, car il peut gérer le chiffre à partir d'une frappe au clavier et également être en mesure de gérer les fonctions Copier + Coller à partir du Presse-papiers. J'espère que mon code VB ci-dessous peut éclairer la situation.

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

Le mieux pour l’ensemble consiste à utiliser la méthode de substitution OnKeyPressed pour la zone de texte, par exemple. Voici le code pour le remplacement utilisant la méthode statique Char IsDigit.

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

C'est tout ce que vous devez vraiment faire.

0
Robert

Ce serait mon approche préférée:

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