web-dev-qa-db-fra.com

Autoriser uniquement les caractères alphanumériques dans la zone de texte

J'ai une zone de texte qui devrait interdire la saisie de caractères spéciaux.

L'utilisateur peut entrer: 

  1. A à Z 
  2. a-z 
  3. 0-9 
  4. Space

Comment puis-je créer l'événement KeyDown pour le faire? 

16
Sauron
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
  {
     if ((e.Key < Key.A) || (e.Key > Key.Z))
        e.Handled = true;
  }
2

La gestion des événements KeyDown ou KeyPress est un moyen d'y parvenir, mais les programmeurs oublient généralement qu'un utilisateur peut toujours copier-coller du texte non valide dans la zone de texte.

Une façon un peu meilleure consiste à gérer l'événement TextChanged et à éliminer tous les caractères incriminés. Ceci est un peu plus compliqué, car vous devez suivre la position du curseur et la redéfinir à l'emplacement approprié après avoir modifié la propriété Text de la boîte.

En fonction des besoins de votre application, je laisserais simplement l'utilisateur taper ce qu'il voudrait, puis marquer la zone de texte (transformer le texte en rouge ou quelque chose du genre) lorsque l'utilisateur essaierait de soumettre.

31
MusiGenesis

Je voulais juste ajouter du code pour ceux qui finissent ici par la recherche:

private void Filter_TextChanged(object sender, EventArgs e)
{
    var textboxSender = (TextBox)sender;
    var cursorPosition = textboxSender.SelectionStart;
    textboxSender.Text = Regex.Replace(textboxSender.Text, "[^0-9a-zA-Z ]", "");
    textboxSender.SelectionStart = cursorPosition;
}

Il s'agit d'un filtre de modification. Il gère donc les opérations de copier-coller et préserve la position du curseur afin que le texte modifié au centre fonctionne correctement.

Notez qu'il utilise "l'expéditeur" pour obtenir le nom du contrôle, ce qui permet de lier cette fonction à plusieurs zones de texte, en supposant qu'elles aient besoin du même filtre. Vous pouvez lier plusieurs contrôles en accédant à la section des événements d'un contrôle et en sélectionnant manuellement la fonction pour l'événement TextChanged.

18
WhoIsRich

Utilisez une regex pour filtrer les autres caractères. Ou utilisez les méthodes Char.IsDigit, IsXXX pour filtrer les caractères indésirables. Beaucoup de façons de le faire.

Mise à jour: Si vous devez utiliser KeyDown, il semble que vous deviez également gérer KeyPressed et définir obEventArgs.Handled = true pour interdire les caractères. Voir l'exemple sur la page KeyDown MSDN

Mise à jour: Maintenant que vous spécifiez qu'il s'agit de WPF. Le code ci-dessous permettra uniquement aux caractères a-z et A-Z d'être entrés dans la zone de texte. Prolongez au besoin ...

private void _txtPath_KeyDown(object sender, KeyEventArgs e)
      {
         if ((e.Key < Key.A) || (e.Key > Key.Z))
            e.Handled = true;
      }

Cela se cassera si vous copiez-collez des choses dans la zone de texte. Validez l'intégralité du texte lorsque l'utilisateur quitte le contrôle ou lorsqu'il clique sur OK/Soumettre, comme le dit MusicGenesis.

9
Gishu

Je pense que cela vaut la peine d'envisager de filtrer l'événement TextChanged de la TextBox. Vous pouvez créer une opération qui supprime tous les caractères non valides de votre chaîne de texte. C'est un peu plus compliqué que de bloquer l'événement KeyDown.

Mais, je pense que c'est la voie à suivre car vous ne bloquez pas les mécanismes de gestion des événements KeyDown/Up intégrés à WPF. Le copier/coller fonctionne donc toujours. Vous travailleriez à un niveau d'abstraction plus élevé, alors je pense qu'il sera plus facile de comprendre ce qui se passe.

3
Szymon Rozga

J'ai couru dans Silverlight et écrit quelque chose comme ça.

private string _filterRegexPattern = "[^a-zA-Z0-9]"; // This would be "[^a-z0-9 ]" for this question.
private int _stringMaxLength = 24;


private void _inputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    if (!string.IsNullOrEmpty(_filterRegexPattern))
    {
        var text = _inputTextBox.Text;
        var newText = Regex.Replace(_inputTextBox.Text, _filterRegexPattern, "");

        if (newText.Length > _stringMaxLength)
        {
            newText = newText.Substring(0, _stringMaxLength);
        }


        if (text.Length != newText.Length)
        {
            var selectionStart = _inputTextBox.SelectionStart - (text.Length - newText.Length);
            _inputTextBox.Text = newText;
            _inputTextBox.SelectionStart = selectionStart;
        }
    }
}
3
shane

J'accomplis cela avec une propriété de dépendance personnalisée. Il est réutilisable pour tout contrôle TextBox, est beaucoup plus rapide et efficace à utiliser que la création d'événements clés et rend mes fichiers de code beaucoup plus propres.

En outre, il peut gérer d'autres méthodes de saisie qui ne déclenchent pas d'événements clés, tels que le collage d'une valeur dans la zone de texte à l'aide de la souris.

Le code du DP personnalisé ressemble à ceci:

// When set to a Regex, the TextBox will only accept characters that match the RegEx

/// <summary>
/// Lets you enter a RegexPattern of what characters are allowed as input in a TextBox
/// </summary>
public static readonly DependencyProperty AllowedCharactersRegexProperty =
    DependencyProperty.RegisterAttached("AllowedCharactersRegex",
                                        typeof(string), typeof(TextBoxProperties),
                                        new UIPropertyMetadata(null, AllowedCharactersRegexChanged));

// Get
public static string GetAllowedCharactersRegex(DependencyObject obj)
{
    return (string)obj.GetValue(AllowedCharactersRegexProperty);
}

// Set
public static void SetAllowedCharactersRegex(DependencyObject obj, string value)
{
    obj.SetValue(AllowedCharactersRegexProperty, value);
}

// Events
public static void AllowedCharactersRegexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var tb = obj as TextBox;
    if (tb != null)
    {
        if (e.NewValue != null)
        {
            tb.PreviewTextInput += Textbox_PreviewTextChanged;
            DataObject.AddPastingHandler(tb, TextBox_OnPaste);
        }
        else
        {
            tb.PreviewTextInput -= Textbox_PreviewTextChanged;
            DataObject.RemovePastingHandler(tb, TextBox_OnPaste);
        }
    }
}

public static void TextBox_OnPaste(object sender, DataObjectPastingEventArgs e)
{
    var tb = sender as TextBox;

    bool isText = e.SourceDataObject.GetDataPresent(DataFormats.Text, true);
    if (!isText) return;

    var newText = e.SourceDataObject.GetData(DataFormats.Text) as string;
    string re = GetAllowedCharactersRegex(tb);
    re = string.Format("[^{0}]", re);

    if (Regex.IsMatch(newText.Trim(), re, RegexOptions.IgnoreCase))
    {
        e.CancelCommand();
    }
}

public static void Textbox_PreviewTextChanged(object sender, TextCompositionEventArgs e)
{
    var tb = sender as TextBox;
    if (tb != null)
    {
        string re = GetAllowedCharactersRegex(tb);
        re = string.Format("[^{0}]", re);

        if (Regex.IsMatch(e.Text, re, RegexOptions.IgnoreCase))
        {
            e.Handled = true;
        }
    }
}

Et c'est utilisé comme ça:

<TextBox Text="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged}" 
         local:TextBoxHelpers.AllowedCharactersRegex="a-zA-Z0-9\s" />
3
Rachel

Le moyen le plus simple de procéder consiste à inclure Extended WPF Toolkit, qui permet de faire exactement ce que vous demandez en spécifiant un masque.

http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home

Il affichera également le masque dans la zone de texte lors de la saisie, le cas échéant.

(Il a aussi beaucoup d'autres contrôles utiles)

2
gr-eg

Je sais que WinForms dispose d’un contrôle MaskedTextBox, qui vous permet de spécifier exactement ce type de chose. Je ne connais pas WPF, donc je ne sais pas si c'est disponible là-bas, mais si c'est le cas, faites-le. C'est BEAUCOUP plus facile que tout ce genre de choses avec des pressions de touche et des événements, et plus robuste aussi.

2
GWLlosa

uniquement TextBox alphanumérique WPF C #,

désolé pour mon anglais .. mais avec ce code pour WPF, c #, je n'autorise que les caractères alphanumériques

private void txtTraslado_TextChanged(object sender, KeyEventArgs e)
{
  if (((e.Key < Key.NumPad0)||(e.Key > Key.NumPad9))&&((e.Key < Key.A)||(e.Key > Key.Z)))
  {
    e.Handled = true;
  }
}
1
miguel

et votre regExp pourrait ressembler à [0-9a-zA-Z] * pour n'autoriser que les caractères alphanumériques anglais

1
Rune FS

Utiliser Asp.NET AJAX Control Toolkit

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

Et utiliser FilteredTextBoxExtender 

<asp:TextBox ID="txt_gpf_no" runat="server" CssClass="textbox" 
                                                MaxLength="10"></asp:TextBox>
<asp:FilteredTextBoxExtender ID="FilteredTextBoxExtender_gpf_no" runat="server" Enabled="True"
                                                TargetControlID="txt_gpf_no" FilterType="UppercaseLetters,LowercaseLetters,Custom" ValidChars="1234567890 ">
</asp:FilteredTextBoxExtender>
0
Mr. P

dans l'application my.Net Framework 4.5 C #

    private void txtRF_Register_Val_KeyDown(object sender, KeyEventArgs e)
    {
        //only enable alphanumeric
        if (!(((e.KeyCode < Keys.NumPad0) || (e.KeyCode > Keys.NumPad9)) && ((e.KeyCode < Keys.A) || (e.KeyCode > Keys.E))))
        {
            e.SuppressKeyPress = false;
        }
        else
        {
            e.SuppressKeyPress = true;
        }
    }
0
Vincent Vrignaud