c# - How do I get a TextBox to only accept numeric input in WPF?

ID : 7267

viewed : 304

Tags : c#wpfxamltextboxnumericupdownc#





Top 5 Answer for c# - How do I get a TextBox to only accept numeric input in WPF?

vote vote

100

Add a preview text input event. Like so: <TextBox PreviewTextInput="PreviewTextInput" />.

Then inside that set the e.Handled if the text isn't allowed. e.Handled = !IsTextAllowed(e.Text);

I use a simple regex in IsTextAllowed method to see if I should allow what they've typed. In my case I only want to allow numbers, dots and dashes.

private static readonly Regex _regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text private static bool IsTextAllowed(string text) {     return !_regex.IsMatch(text); } 

If you want to prevent pasting of incorrect data hook up the DataObject.Pasting event DataObject.Pasting="TextBoxPasting" as shown here (code excerpted):

// Use the DataObject.Pasting Handler  private void TextBoxPasting(object sender, DataObjectPastingEventArgs e) {     if (e.DataObject.GetDataPresent(typeof(String)))     {         String text = (String)e.DataObject.GetData(typeof(String));         if (!IsTextAllowed(text))         {             e.CancelCommand();         }     }     else     {         e.CancelCommand();     } } 
vote vote

87

The event handler is previewing text input. Here a regular expression matches the text input only if it is not a number, and then it is not made to entry textbox.

If you want only letters then replace the regular expression as [^a-zA-Z].

XAML

<TextBox Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox"/> 

XAML.CS FILE

using System.Text.RegularExpressions; private void NumberValidationTextBox(object sender, TextCompositionEventArgs e) {     Regex regex = new Regex("[^0-9]+");     e.Handled = regex.IsMatch(e.Text); } 
vote vote

79

I used some of what was already here and put my own twist on it using a behavior so I don't have to propagate this code throughout a ton of Views...

public class AllowableCharactersTextBoxBehavior : Behavior<TextBox> {     public static readonly DependencyProperty RegularExpressionProperty =          DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),          new FrameworkPropertyMetadata(".*"));     public string RegularExpression     {         get         {             return (string)base.GetValue(RegularExpressionProperty);         }         set         {             base.SetValue(RegularExpressionProperty, value);         }     }      public static readonly DependencyProperty MaxLengthProperty =         DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),         new FrameworkPropertyMetadata(int.MinValue));     public int MaxLength     {         get         {             return (int)base.GetValue(MaxLengthProperty);         }         set         {             base.SetValue(MaxLengthProperty, value);         }     }      protected override void OnAttached()     {         base.OnAttached();         AssociatedObject.PreviewTextInput += OnPreviewTextInput;         DataObject.AddPastingHandler(AssociatedObject, OnPaste);     }      private void OnPaste(object sender, DataObjectPastingEventArgs e)     {         if (e.DataObject.GetDataPresent(DataFormats.Text))         {             string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));              if (!IsValid(text, true))             {                 e.CancelCommand();             }         }         else         {             e.CancelCommand();         }     }      void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)     {         e.Handled = !IsValid(e.Text, false);     }      protected override void OnDetaching()     {         base.OnDetaching();         AssociatedObject.PreviewTextInput -= OnPreviewTextInput;         DataObject.RemovePastingHandler(AssociatedObject, OnPaste);     }      private bool IsValid(string newText, bool paste)     {         return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);     }      private bool ExceedsMaxLength(string newText, bool paste)     {         if (MaxLength == 0) return false;          return LengthOfModifiedText(newText, paste) > MaxLength;     }      private int LengthOfModifiedText(string newText, bool paste)     {         var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;         var caretIndex = this.AssociatedObject.CaretIndex;         string text = this.AssociatedObject.Text;          if (countOfSelectedChars > 0 || paste)         {             text = text.Remove(caretIndex, countOfSelectedChars);             return text.Length + newText.Length;         }         else         {             var insert = Keyboard.IsKeyToggled(Key.Insert);              return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;         }     } } 

Here is the relevant view code:

<TextBox MaxLength="50" TextWrapping="Wrap" MaxWidth="150" Margin="4"  Text="{Binding Path=FileNameToPublish}" >      <interactivity:Interaction.Behaviors>          <v:AllowableCharactersTextBoxBehavior RegularExpression="^[0-9.\-]+$" MaxLength="50" />      </interactivity:Interaction.Behaviors> </TextBox> 
vote vote

68

This is an improved solution of WilPs answer. My improvements are:

  • Improved behaviour on Del and Backspace buttons
  • Added EmptyValue property, if empty string is inappropriate
  • Fixed some minor typos
/// <summary> ///     Regular expression for Textbox with properties:  ///         <see cref="RegularExpression"/>,  ///         <see cref="MaxLength"/>, ///         <see cref="EmptyValue"/>. /// </summary> public class TextBoxInputRegExBehaviour : Behavior<TextBox> {     #region DependencyProperties     public static readonly DependencyProperty RegularExpressionProperty =         DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*"));      public string RegularExpression     {         get { return (string)GetValue(RegularExpressionProperty); }         set { SetValue(RegularExpressionProperty, value); }     }      public static readonly DependencyProperty MaxLengthProperty =         DependencyProperty.Register("MaxLength", typeof(int), typeof(TextBoxInputRegExBehaviour),                                         new FrameworkPropertyMetadata(int.MinValue));      public int MaxLength     {         get { return (int)GetValue(MaxLengthProperty); }         set { SetValue(MaxLengthProperty, value); }     }      public static readonly DependencyProperty EmptyValueProperty =         DependencyProperty.Register("EmptyValue", typeof(string), typeof(TextBoxInputRegExBehaviour), null);      public string EmptyValue     {         get { return (string)GetValue(EmptyValueProperty); }         set { SetValue(EmptyValueProperty, value); }     }     #endregion      /// <summary>     ///     Attach our behaviour. Add event handlers     /// </summary>     protected override void OnAttached()     {         base.OnAttached();          AssociatedObject.PreviewTextInput += PreviewTextInputHandler;         AssociatedObject.PreviewKeyDown += PreviewKeyDownHandler;         DataObject.AddPastingHandler(AssociatedObject, PastingHandler);     }      /// <summary>     ///     Deattach our behaviour. remove event handlers     /// </summary>     protected override void OnDetaching()     {         base.OnDetaching();          AssociatedObject.PreviewTextInput -= PreviewTextInputHandler;         AssociatedObject.PreviewKeyDown -= PreviewKeyDownHandler;         DataObject.RemovePastingHandler(AssociatedObject, PastingHandler);     }      #region Event handlers [PRIVATE] --------------------------------------      void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)     {         string text;         if (this.AssociatedObject.Text.Length < this.AssociatedObject.CaretIndex)             text = this.AssociatedObject.Text;         else         {             //  Remaining text after removing selected text.             string remainingTextAfterRemoveSelection;              text = TreatSelectedText(out remainingTextAfterRemoveSelection)                 ? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text)                 : AssociatedObject.Text.Insert(this.AssociatedObject.CaretIndex, e.Text);         }          e.Handled = !ValidateText(text);     }      /// <summary>     ///     PreviewKeyDown event handler     /// </summary>     void PreviewKeyDownHandler(object sender, KeyEventArgs e)     {         if (string.IsNullOrEmpty(this.EmptyValue))             return;          string text = null;          // Handle the Backspace key         if (e.Key == Key.Back)         {             if (!this.TreatSelectedText(out text))             {                 if (AssociatedObject.SelectionStart > 0)                     text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart - 1, 1);             }         }         // Handle the Delete key         else if (e.Key == Key.Delete)         {             // If text was selected, delete it             if (!this.TreatSelectedText(out text) && this.AssociatedObject.Text.Length > AssociatedObject.SelectionStart)             {                 // Otherwise delete next symbol                 text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, 1);             }         }          if (text == string.Empty)         {             this.AssociatedObject.Text = this.EmptyValue;             if (e.Key == Key.Back)                 AssociatedObject.SelectionStart++;             e.Handled = true;         }     }      private void PastingHandler(object sender, DataObjectPastingEventArgs e)     {         if (e.DataObject.GetDataPresent(DataFormats.Text))         {             string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));              if (!ValidateText(text))                 e.CancelCommand();         }         else             e.CancelCommand();     }     #endregion Event handlers [PRIVATE] -----------------------------------      #region Auxiliary methods [PRIVATE] -----------------------------------      /// <summary>     ///     Validate certain text by our regular expression and text length conditions     /// </summary>     /// <param name="text"> Text for validation </param>     /// <returns> True - valid, False - invalid </returns>     private bool ValidateText(string text)     {         return (new Regex(this.RegularExpression, RegexOptions.IgnoreCase)).IsMatch(text) && (MaxLength == int.MinValue || text.Length <= MaxLength);     }      /// <summary>     ///     Handle text selection     /// </summary>     /// <returns>true if the character was successfully removed; otherwise, false. </returns>     private bool TreatSelectedText(out string text)     {         text = null;         if (AssociatedObject.SelectionLength <= 0)              return false;          var length = this.AssociatedObject.Text.Length;         if (AssociatedObject.SelectionStart >= length)             return true;          if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length)             AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart;          text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength);         return true;     }     #endregion Auxiliary methods [PRIVATE] -------------------------------- } 

Usage is pretty straightforward:

<i:Interaction.Behaviors>     <behaviours:TextBoxInputRegExBehaviour RegularExpression="^\d+$" MaxLength="9" EmptyValue="0" /> </i:Interaction.Behaviors> 
vote vote

55

Here is a very simple and easy way to do this using MVVM.

Bind your textBox with an integer property in the view model, and this will work like a gem ... it will even show validation when a non-integer is entered in the textbox.

XAML code:

<TextBox x:Name="contactNoTxtBox"  Text="{Binding contactNo}" /> 

View model code:

private long _contactNo; public long contactNo {     get { return _contactNo; }     set     {         if (value == _contactNo)             return;         _contactNo = value;         OnPropertyChanged();     } } 

Top 3 video Explaining c# - How do I get a TextBox to only accept numeric input in WPF?







Related QUESTION?