2012-09-26 16 views
11

Come posso consentire solo determinati caratteri in una casella di testo di Visual C#? Gli utenti dovrebbero essere in grado di inserire i seguenti caratteri in una casella di testo e tutto il resto dovrebbe essere bloccato: 0-9, +, -, /, *, (,).Consentono solo caratteri specifici nella casella di testo

Ho usato Google per cercare questo problema, ma le uniche soluzioni che sto ottenendo sono solo caratteri alfabetici, solo numeri o non consentono determinati caratteri. Quello che voglio non è disabilitare alcuni personaggi, voglio disabilitare tutto per impostazione predefinita tranne i caratteri che ho inserito nel codice.

+4

ASP.NET? WinForms? WPF? Tutti questi possono usare C# e tutti sono diversi. – David

+0

È un'applicazione Windows Form. –

+1

Hai provato a creare un gestore di eventi per l'evento PropertyChanged che elimina il carattere se non è valido? –

risposta

23

Come menzionato in un commento (e un'altra risposta mentre scrivevo) è necessario registrare un gestore di eventi per catturare l'evento keydown o keypress su una casella di testo. Questo perché TextChanged viene generato solo quando il TextBox perde lo stato attivo

Il sotto espressione regolare permette di abbinare questi personaggi si desidera consentire

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

e questo fa il contrario e cattura i caratteri che non sono consentiti

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

Non sto assumendo che ci sarà una singola corrispondenza in quanto qualcuno potrebbe incollare il testo nella casella di testo. nel qual caso cattura TextChanged

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 
    } 
} 

e per convalidare la pressione dei tasti singoli

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; 
    } 
} 
+2

si potrebbe voler aggiungere un controllo extra per la chiave con il codice 8, altrimenti il ​​backspace non funzionerà – imaximchuk

+0

Nel caso in cui qualcun altro si imbattesse in questo ... Non ero in grado di farlo funzionare nel gestore di 'KeyPress'. Anche se ho impostato 'e.Handled' su' true', è ancora possibile inserire il carattere nel controllo. Quando sono passato a gestire 'KeyDown' invece, tutto ha funzionato bene. Il controllo che sto usando è un 'RichTextBox', quindi potrebbe avere qualcosa a che fare con esso. Non ho sperimentato molto dopo averlo fatto funzionare. – danBhentschel

+1

Come nota a margine, TextChanged non viene attivato quando il testo perde lo stato attivo, ma subito dopo una modifica nel testo (ad esempio, lo utilizzo per colorare un testo se è valido). È troppo tardi difficile. – Teejay

1

È possibile utilizzare probabilmente lo KeyDown event, KeyPress event o KeyUp event. Vorrei prima provare l'evento KeyDown che penso.

È possibile impostare la proprietà Handled degli argomenti dell'evento per interrompere la gestione dell'evento.

0

Per l'evento di convalida IMO il metodo più semplice sarebbe utilizzare un array di caratteri per convalidare i caratteri della casella di testo. True - iterare e validare non è particolarmente efficiente, ma è semplice.

In alternativa, utilizzare un'espressione regolare dei caratteri della whitelist sulla stringa di input. I tuoi eventi sono disponibili all'indirizzo MSDN qui: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

10

È necessario sottoscrivere l'evento KeyDown sulla casella di testo. Poi qualcosa di simile:

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; 
} 

La cosa importante da sapere è che se è stata modificata la proprietà Handled per true, non elaborerà la sequenza di tasti. Impostandolo a false sarà.

-1
private void txtuser_KeyPress(object sender, KeyPressEventArgs e) 
    { 
     if (!char.IsLetter(e.KeyChar) && !char.IsWhiteSpace(e.KeyChar) && !char.IsControl(e.KeyChar)) 
     { 
      e.Handled = true; 
     } 
    } 
0

Intercettare l'evento KeyPressed è a mio parere una buona soluzione solida. Prestare attenzione ai caratteri del codice di attivazione (e.KeyChar inferiore a 32) se si utilizza un RegExp.

In questo modo è comunque possibile iniettare caratteri fuori intervallo ogni volta che l'utente incolla il testo dagli Appunti. Purtroppo non ho trovato gli eventi degli appunti corretti per risolvere questo problema.

Quindi una soluzione impermeabile è quella di intercettare TextBox.TextChanged. Qui a volte è visibile il carattere originale fuori intervallo, per un breve periodo. Consiglio di implementare entrambi.

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; 
} 
Problemi correlati