How do I get a TextBox to only accept numeric input in WPF?
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 textprivate 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(); }}
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);}
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>