Comment définir les ressortingctions d’entrée TextBox?

Comment puis-je restreindre TextBox pour accepter uniquement les majuscules, ou par exemple des chiffres, ou interdire de mettre un caractère spécial?

Bien sûr, attraper un événement TextInput et gérer le texte ici est un jeu d’enfant, mais est-ce la bonne façon de le faire?

Je l’ai fait par le passé avec un comportement attaché, qui peut être utilisé comme ceci:

 

Le code de comportement ci-joint ressemble à ceci:

 ///  /// Provides masking behavior for any . ///  public static class Masking { private static readonly DependencyPropertyKey _maskExpressionPropertyKey = DependencyProperty.RegisterAttachedReadOnly("MaskExpression", typeof(Regex), typeof(Masking), new FrameworkPropertyMetadata()); ///  /// Identifies the  dependency property. ///  public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask", typeof(ssortingng), typeof(Masking), new FrameworkPropertyMetadata(OnMaskChanged)); ///  /// Identifies the  dependency property. ///  public static readonly DependencyProperty MaskExpressionProperty = _maskExpressionPropertyKey.DependencyProperty; ///  /// Gets the mask for a given . ///  ///  /// The  whose mask is to be resortingeved. ///  ///  /// The mask, or  if no mask has been set. ///  public static ssortingng GetMask(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskProperty) as ssortingng; } ///  /// Sets the mask for a given . ///  ///  /// The  whose mask is to be set. ///  ///  /// The mask to set, or  to remove any existing mask from . ///  public static void SetMask(TextBox textBox, ssortingng mask) { if (textBox == null) { throw new ArgumentNullException("textBox"); } textBox.SetValue(MaskProperty, mask); } ///  /// Gets the mask expression for the . ///  ///  /// This method can be used to resortingeve the actual  instance created as a result of setting the mask on a . ///  ///  /// The  whose mask expression is to be resortingeved. ///  ///  /// The mask expression as an instance of , or  if no mask has been applied to . ///  public static Regex GetMaskExpression(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskExpressionProperty) as Regex; } private static void SetMaskExpression(TextBox textBox, Regex regex) { textBox.SetValue(_maskExpressionPropertyKey, regex); } private static void OnMaskChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { var textBox = dependencyObject as TextBox; var mask = e.NewValue as ssortingng; textBox.PreviewTextInput -= textBox_PreviewTextInput; textBox.PreviewKeyDown -= textBox_PreviewKeyDown; DataObject.RemovePastingHandler(textBox, Pasting); if (mask == null) { textBox.ClearValue(MaskProperty); textBox.ClearValue(MaskExpressionProperty); } else { textBox.SetValue(MaskProperty, mask); SetMaskExpression(textBox, new Regex(mask, RegexOptions.Comstackd | RegexOptions.IgnorePatternWhitespace)); textBox.PreviewTextInput += textBox_PreviewTextInput; textBox.PreviewKeyDown += textBox_PreviewKeyDown; DataObject.AddPastingHandler(textBox, Pasting); } } private static void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } var proposedText = GetProposedText(textBox, e.Text); if (!maskExpression.IsMatch(proposedText)) { e.Handled = true; } } private static void textBox_PreviewKeyDown(object sender, KeyEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } //pressing space doesn't raise PreviewTextInput - no idea why, but we need to handle //explicitly here if (e.Key == Key.Space) { var proposedText = GetProposedText(textBox, " "); if (!maskExpression.IsMatch(proposedText)) { e.Handled = true; } } } private static void Pasting(object sender, DataObjectPastingEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } if (e.DataObject.GetDataPresent(typeof(ssortingng))) { var pastedText = e.DataObject.GetData(typeof(ssortingng)) as ssortingng; var proposedText = GetProposedText(textBox, pastedText); if (!maskExpression.IsMatch(proposedText)) { e.CancelCommand(); } } else { e.CancelCommand(); } } private static ssortingng GetProposedText(TextBox textBox, ssortingng newText) { var text = textBox.Text; if (textBox.SelectionStart != -1) { text = text.Remove(textBox.SelectionStart, textBox.SelectionLength); } text = text.Insert(textBox.CaretIndex, newText); return text; } } 

J’ai amélioré la réponse de Kent Boogaart en gérant également les actions suivantes qui, auparavant, pouvaient entraîner la violation du motif:

  • Retour arrière
  • Sélectionner et faire glisser le texte de manière à violer le motif
  • Commande de coupe

Par exemple, la réponse de Kent Boogaart a permis à l’utilisateur d’entrer “ac” en entrant d’abord “abc” et ensuite de supprimer le “b” avec le retour arrière qui viole la regex suivante

 ^(a|ab|abc)$ 

Utilisation (inchangé):

Classe de masque:

 public static class Masking { private static readonly DependencyPropertyKey _maskExpressionPropertyKey = DependencyProperty.RegisterAttachedReadOnly("MaskExpression", typeof(Regex), typeof(Masking), new FrameworkPropertyMetadata()); ///  /// Identifies the  dependency property. ///  public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask", typeof(ssortingng), typeof(Masking), new FrameworkPropertyMetadata(OnMaskChanged)); ///  /// Identifies the  dependency property. ///  public static readonly DependencyProperty MaskExpressionProperty = _maskExpressionPropertyKey.DependencyProperty; ///  /// Gets the mask for a given . ///  ///  /// The  whose mask is to be resortingeved. ///  ///  /// The mask, or  if no mask has been set. ///  public static ssortingng GetMask(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskProperty) as ssortingng; } ///  /// Sets the mask for a given . ///  ///  /// The  whose mask is to be set. ///  ///  /// The mask to set, or  to remove any existing mask from . ///  public static void SetMask(TextBox textBox, ssortingng mask) { if (textBox == null) { throw new ArgumentNullException("textBox"); } textBox.SetValue(MaskProperty, mask); } ///  /// Gets the mask expression for the . ///  ///  /// This method can be used to resortingeve the actual  instance created as a result of setting the mask on a . ///  ///  /// The  whose mask expression is to be resortingeved. ///  ///  /// The mask expression as an instance of , or  if no mask has been applied to . ///  public static Regex GetMaskExpression(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskExpressionProperty) as Regex; } private static void SetMaskExpression(TextBox textBox, Regex regex) { textBox.SetValue(_maskExpressionPropertyKey, regex); } private static void OnMaskChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { var textBox = dependencyObject as TextBox; var mask = e.NewValue as ssortingng; textBox.PreviewTextInput -= textBox_PreviewTextInput; textBox.PreviewKeyDown -= textBox_PreviewKeyDown; DataObject.RemovePastingHandler(textBox, Pasting); DataObject.RemoveCopyingHandler(textBox, NoDragCopy); CommandManager.RemovePreviewExecutedHandler(textBox, NoCutting); if (mask == null) { textBox.ClearValue(MaskProperty); textBox.ClearValue(MaskExpressionProperty); } else { textBox.SetValue(MaskProperty, mask); SetMaskExpression(textBox, new Regex(mask, RegexOptions.Comstackd | RegexOptions.IgnorePatternWhitespace)); textBox.PreviewTextInput += textBox_PreviewTextInput; textBox.PreviewKeyDown += textBox_PreviewKeyDown; DataObject.AddPastingHandler(textBox, Pasting); DataObject.AddCopyingHandler(textBox, NoDragCopy); CommandManager.AddPreviewExecutedHandler(textBox, NoCutting); } } private static void NoCutting(object sender, ExecutedRoutedEventArgs e) { if(e.Command == ApplicationCommands.Cut) { e.Handled = true; } } private static void NoDragCopy(object sender, DataObjectCopyingEventArgs e) { if (e.IsDragDrop) { e.CancelCommand(); } } private static void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } var proposedText = GetProposedText(textBox, e.Text); if (!maskExpression.IsMatch(proposedText)) { e.Handled = true; } } private static void textBox_PreviewKeyDown(object sender, KeyEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } ssortingng proposedText = null; //pressing space doesn't raise PreviewTextInput, reasons here http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b?prof=required if (e.Key == Key.Space) { proposedText = GetProposedText(textBox, " "); } // Same story with backspace else if(e.Key == Key.Back) { proposedText = GetProposedTextBackspace(textBox); } if (proposedText != null && proposedText != ssortingng.Empty && !maskExpression.IsMatch(proposedText)) { e.Handled = true; } } private static void Pasting(object sender, DataObjectPastingEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); if (maskExpression == null) { return; } if (e.DataObject.GetDataPresent(typeof(ssortingng))) { var pastedText = e.DataObject.GetData(typeof(ssortingng)) as ssortingng; var proposedText = GetProposedText(textBox, pastedText); if (!maskExpression.IsMatch(proposedText)) { e.CancelCommand(); } } else { e.CancelCommand(); } } private static ssortingng GetProposedTextBackspace(TextBox textBox) { var text = GetTextWithSelectionRemoved(textBox); if (textBox.SelectionStart > 0 && textBox.SelectionLength == 0) { text = text.Remove(textBox.SelectionStart-1, 1); } return text; } private static ssortingng GetProposedText(TextBox textBox, ssortingng newText) { var text = GetTextWithSelectionRemoved(textBox); text = text.Insert(textBox.CaretIndex, newText); return text; } private static ssortingng GetTextWithSelectionRemoved(TextBox textBox) { var text = textBox.Text; if (textBox.SelectionStart != -1) { text = text.Remove(textBox.SelectionStart, textBox.SelectionLength); } return text; } } 

J’ai changé le code de VitalyB pour prendre en charge les thèmes de couleur. Au lieu de bloquer les entrées utilisateur s’il ne respecte pas le script RegEx, il met simplement en surbrillance la zone de texte. La zone de texte sera la valeur par défaut du thème sans interaction, puis par défaut un vert clair ou un rouge selon la valeur après la définition de l’entrée. Vous pouvez également définir les couleurs d’échec et de réussite par programme avec:

 b:ColorMasking.PassColor = "Hexadecimal Value" b:ColorMasking.FailColor = "Hexadecimal Value" 

La classe est ci-dessous:

 public class ColorMasking : DependencyObject { private static readonly DependencyPropertyKey _maskExpressionPropertyKey = DependencyProperty.RegisterAttachedReadOnly("MaskExpression", typeof(Regex), typeof(ColorMasking), new FrameworkPropertyMetadata()); ///  /// Identifies the  dependency property. ///  /// public static readonly DependencyProperty PassColorProperty = DependencyProperty.RegisterAttached("PassColor", typeof(ssortingng), typeof(ColorMasking), new PropertyMetadata("#99FF99")); public static void SetPassColor(DependencyObject obj, ssortingng passColor) { obj.SetValue(PassColorProperty, passColor); } public static ssortingng GetPassColor(DependencyObject obj) { return (ssortingng)obj.GetValue(PassColorProperty); } public static readonly DependencyProperty FailColorProperty = DependencyProperty.RegisterAttached("FailColor", typeof(ssortingng), typeof(ColorMasking), new PropertyMetadata("#FFCCFF")); public static void SetFailColor(DependencyObject obj, ssortingng failColor) { obj.SetValue(FailColorProperty, failColor); } public static ssortingng GetFailColor(DependencyObject obj) { return (ssortingng)obj.GetValue(FailColorProperty); } public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask", typeof(ssortingng), typeof(ColorMasking), new FrameworkPropertyMetadata(OnMaskChanged)); private static void OnPassColorChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { var textBox = dependencyObject as TextBox; var color = e.NewValue as ssortingng; textBox.SetValue(PassColorProperty, color); } ///  /// Identifies the  dependency property. ///  public static readonly DependencyProperty MaskExpressionProperty = _maskExpressionPropertyKey.DependencyProperty; ///  /// Gets the mask for a given . ///  ///  /// The  whose mask is to be resortingeved. ///  ///  /// The mask, or  if no mask has been set. ///  public static ssortingng GetMask(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskProperty) as ssortingng; } ///  /// Sets the mask for a given . ///  ///  /// The  whose mask is to be set. ///  ///  /// The mask to set, or  to remove any existing mask from . ///  public static void SetMask(TextBox textBox, ssortingng mask) { if (textBox == null) { throw new ArgumentNullException("textBox"); } textBox.SetValue(MaskProperty, mask); } ///  /// Gets the mask expression for the . ///  ///  /// This method can be used to resortingeve the actual  instance created as a result of setting the mask on a . ///  ///  /// The  whose mask expression is to be resortingeved. ///  ///  /// The mask expression as an instance of , or  if no mask has been applied to . ///  public static Regex GetMaskExpression(TextBox textBox) { if (textBox == null) { throw new ArgumentNullException("textBox"); } return textBox.GetValue(MaskExpressionProperty) as Regex; } private static void SetMaskExpression(TextBox textBox, Regex regex) { textBox.SetValue(_maskExpressionPropertyKey, regex); } private static void OnMaskChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { var textBox = dependencyObject as TextBox; var mask = e.NewValue as ssortingng; textBox.PreviewTextInput -= textBox_PreviewTextInput; textBox.PreviewKeyDown -= textBox_PreviewKeyDown; DataObject.RemovePastingHandler(textBox, Pasting); DataObject.RemoveCopyingHandler(textBox, NoDragCopy); CommandManager.RemovePreviewExecutedHandler(textBox, NoCutting); if (mask == null) { textBox.ClearValue(MaskProperty); textBox.ClearValue(MaskExpressionProperty); } else { textBox.SetValue(MaskProperty, mask); SetMaskExpression(textBox, new Regex(mask, RegexOptions.Comstackd | RegexOptions.IgnorePatternWhitespace)); textBox.PreviewTextInput += textBox_PreviewTextInput; textBox.PreviewKeyDown += textBox_PreviewKeyDown; DataObject.AddPastingHandler(textBox, Pasting); DataObject.AddCopyingHandler(textBox, NoDragCopy); CommandManager.AddPreviewExecutedHandler(textBox, NoCutting); } } private static void NoCutting(object sender, ExecutedRoutedEventArgs e) { if (e.Command == ApplicationCommands.Cut) { e.Handled = true; } } private static void NoDragCopy(object sender, DataObjectCopyingEventArgs e) { if (e.IsDragDrop) { e.CancelCommand(); } } private static void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); ssortingng passHex = (ssortingng)textBox.GetValue(PassColorProperty); ssortingng failHex = (ssortingng)textBox.GetValue(FailColorProperty); Color passColor = Extensions.ToColorFromHex(passHex); Color failColor = Extensions.ToColorFromHex(failHex); if (maskExpression == null) { return; } var proposedText = GetProposedText(textBox, e.Text); if (!maskExpression.IsMatch(proposedText)) { textBox.Background = new SolidColorBrush(failColor); } else { textBox.Background = new SolidColorBrush(passColor); } } private static void textBox_PreviewKeyDown(object sender, KeyEventArgs e) { var textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); ssortingng passHex = (ssortingng)textBox.GetValue(PassColorProperty); ssortingng failHex = (ssortingng)textBox.GetValue(FailColorProperty); Color passColor = Extensions.ToColorFromHex(passHex); Color failColor = Extensions.ToColorFromHex(failHex); if (maskExpression == null) { return; } ssortingng proposedText = null; //pressing space doesn't raise PreviewTextInput, reasons here http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b?prof=required if (e.Key == Key.Space) { proposedText = GetProposedText(textBox, " "); } // Same story with backspace else if (e.Key == Key.Back) { proposedText = GetProposedTextBackspace(textBox); } if (proposedText != null && !maskExpression.IsMatch(proposedText)) { textBox.Background = new SolidColorBrush(failColor); } else { textBox.Background = new SolidColorBrush(passColor); } } private static void Pasting(object sender, DataObjectPastingEventArgs e) { TextBox textBox = sender as TextBox; var maskExpression = GetMaskExpression(textBox); ssortingng passHex = (ssortingng)textBox.GetValue(PassColorProperty); ssortingng failHex = (ssortingng)textBox.GetValue(FailColorProperty); Color passColor = Extensions.ToColorFromHex(passHex); Color failColor = Extensions.ToColorFromHex(failHex); if (maskExpression == null) { return; } if (e.DataObject.GetDataPresent(typeof(ssortingng))) { var pastedText = e.DataObject.GetData(typeof(ssortingng)) as ssortingng; var proposedText = GetProposedText(textBox, pastedText); if (!maskExpression.IsMatch(proposedText)) { textBox.Background = new SolidColorBrush(failColor); } else { textBox.Background = new SolidColorBrush(passColor); } } else { textBox.Background = new SolidColorBrush(failColor); } } private static ssortingng GetProposedTextBackspace(TextBox textBox) { var text = GetTextWithSelectionRemoved(textBox); if (textBox.SelectionStart > 0) { text = text.Remove(textBox.SelectionStart - 1, 1); } return text; } private static ssortingng GetProposedText(TextBox textBox, ssortingng newText) { var text = GetTextWithSelectionRemoved(textBox); text = text.Insert(textBox.CaretIndex, newText); return text; } private static ssortingng GetTextWithSelectionRemoved(TextBox textBox) { var text = textBox.Text; if (textBox.SelectionStart != -1) { text = text.Remove(textBox.SelectionStart, textBox.SelectionLength); } return text; } } 

Pour exécuter, le script nécessite une classe écrite par Aaron C, expliquée ici: Silverlight / WPF définit l’ellipse avec une couleur hexadécimale ici: http://www.wiredprairie.us/blog/index.php/archives/659

Le code est ci-dessous si le site Web est déplacé:

 public static class Extensions { public static void SetFromHex(this Color c, ssortingng hex) { Color c1 = ToColorFromHex(hex); cA = c1.A; cR = c1.R; cG = c1.G; cB = c1.B; } public static Color ToColorFromHex(ssortingng hex) { if (ssortingng.IsNullOrEmpty(hex)) { throw new ArgumentNullException("hex"); } // remove any "#" characters while (hex.StartsWith("#")) { hex = hex.Subssortingng(1); } int num = 0; // get the number out of the ssortingng if (!Int32.TryParse(hex, System.Globalization.NumberStyles.HexNumber, null, out num)) { throw new ArgumentException("Color not in a recognized Hex format."); } int[] pieces = new int[4]; if (hex.Length > 7) { pieces[0] = ((num >> 24) & 0x000000ff); pieces[1] = ((num >> 16) & 0x000000ff); pieces[2] = ((num >> 8) & 0x000000ff); pieces[3] = (num & 0x000000ff); } else if (hex.Length > 5) { pieces[0] = 255; pieces[1] = ((num >> 16) & 0x000000ff); pieces[2] = ((num >> 8) & 0x000000ff); pieces[3] = (num & 0x000000ff); } else if (hex.Length == 3) { pieces[0] = 255; pieces[1] = ((num >> 8) & 0x0000000f); pieces[1] += pieces[1] * 16; pieces[2] = ((num >> 4) & 0x000000f); pieces[2] += pieces[2] * 16; pieces[3] = (num & 0x000000f); pieces[3] += pieces[3] * 16; } return Color.FromArgb((byte)pieces[0], (byte)pieces[1], (byte)pieces[2], (byte)pieces[3]); } } 
 private void TextBox1_SelectionChanged(object sender, RoutedEventArgs e) { ssortingng txt = TextBox1.Text; if (txt != "") { TextBox1.Text = Regex.Replace(TextBox1.Text, "[^0-9]", ""); if (txt != TextBox1.Text) { TextBox1.Select(TextBox1.Text.Length, 0); } } } 

Une autre solution possible consiste à utiliser l’une des implémentations wpf “Masked TextBox” en utilisant la classe “MaskedTextProvider” utilisée par “MaskedTextBox” de Winforms.

Deux solutions possibles se trouvent ici -> https://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox et ici -> http://marlongrech.wordpress.com/2007/10/28/masked-textbox/