如何让文本框只接受WPF中的数字input?

我正在寻找接受数字和小数点,但没有迹象。

我已经使用WinForms 的NumericUpDown控件和Microsoft的NumericUpDown自定义控件的示例查看了示例。 但到目前为止,似乎NumericUpDown(WPF支持或不支持)不会提供我想要的function。 我的应用程序的devise方式,没有谁在他们正确的思想是要混乱的箭头。 他们没有任何实际意义,在我的应用程序的上下文中。

所以我正在寻找一个简单的方法来使一个标准的WPF文本框只接受我想要的字符。 这可能吗? 这是否实用?

添加预览文本input事件。 像这样: <TextBox PreviewTextInput="PreviewTextInput" />

然后在里面设置e.Handled如果文本是不允许的。 e.Handled = !IsTextAllowed(e.Text);

我在IsTextAllowed方法中使用了一个简单的正则expression式来查看我是否应该允许他们input的内容。 在我的情况下,我只想让数字,点和破折号。

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

如果要防止粘贴不正确的数据,请将DataObject.Pasting事件的DataObject.Pasting="TextBoxPasting"连接起来(代码摘录):

 // 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(); } } 

事件处理程序是预览文本input。 这里的正则expression式只能匹配文本input,如果它不是一个数字,那么它不是input文本框。 如果只需要字母表,则将正则expression式replace为[^a-zA-Z]

XAML

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

XAML.CS文件

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

使用一些已经在这里,并把我自己的扭曲使用一种行为,所以我不必传播这个代码遍布大量的视图…

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

这里是相关的视图代码。

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

这是WilP答案的一个改进的解答。 我的改进是:

  • 改进DelBackspacebutton的行为
  • 如果空string不合适,则添加EmptyValue属性
  • 修正了一些小错别字
 /// <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] -------------------------------- } 

用法非常简单:

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

添加validation规则,当文本改变时检查以确定数据是否是数字,如果是,则允许处理继续,如果不是,则提示用户在该字段中只接受数字数据。

在这里阅读更多: http : //www.codeproject.com/KB/WPF/wpfvalidation.aspx

Extented WPF Toolkit有一个: NumericUpDown 在这里输入图像描述

也可以简单地实现一个validation规则并将其应用到TextBox中:

  <TextBox> <TextBox.Text> <Binding Path="OnyDigitInput" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <conv:OnlyDigitsValidationRule /> </Binding.ValidationRules> </Binding> </TextBox.Text> 

随着规则的执行如下(使用与其他答案中提出的相同的正则expression式):

 public class OnlyDigitsValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { var validationResult = new ValidationResult(true, null); if(value != null) { if (!string.IsNullOrEmpty(value.ToString())) { var regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text var parsingOk = !regex.IsMatch(value.ToString()); if (!parsingOk) { validationResult = new ValidationResult(false, "Illegal Characters, Please Enter Numeric Value"); } } } return validationResult; } } 

我允许数字键盘和退格键:

  private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) { int key = (int)e.Key; e.Handled = !(key >= 34 && key <= 43 || key >= 74 && key <= 83 || key == 2); } 

希望它有帮助。

我会假设:

  1. 您希望允许数字input的TextBox仅将其Text属性初始设置为某个有效的数字值(例如2.7172)。

  2. 您的文本框是您的主窗口的孩子

  3. 你的主窗口是Window1类

  4. 您的TextBox名称是numericTB

基本理念:

  1. 添加: private string previousText; 到你的主窗口类(Window1)

  2. 添加: previousText = numericTB.Text; 到你的主窗口构造函数

  3. 为numericTB.TextChanged事件创build处理程序是这样的

     private void numericTB_TextChanged(object sender, TextChangedEventArgs e) { double num = 0; bool success = double.TryParse(((TextBox)sender).Text, out num); if (success & num >= 0) previousText = ((TextBox)sender).Text; else ((TextBox)sender).Text = previousText; } 

这将保持设置previousText为numericTB.Text只要它是有效的,并将numericTB.Text设置为最后一个有效值,如果用户写一些你不喜欢的东西。 当然,这只是基本的想法,它只是“白痴抵制”,而不是“白痴certificate”。 例如,它不处理用户混乱空间的情况。 所以这里是完整的解决scheme,我认为是“白痴certificate”,如果我错了,请告诉我:

  1. 你的Window1.xaml文件的内容:

     <Window x:Class="IdiotProofNumericTextBox.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <TextBox Height="30" Width="100" Name="numericTB" TextChanged="numericTB_TextChanged"/> </Grid> </Window> 
  2. 你的Window.xaml.cs文件的内容:

     using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace IdiotProofNumericTextBox { public partial class Window1 : Window { private string previousText; public Window1() { InitializeComponent(); previousText = numericTB.Text; } private void numericTB_TextChanged(object sender, TextChangedEventArgs e) { if (string.IsNullOrEmpty(((TextBox)sender).Text)) previousText = ""; else { double num = 0; bool success = double.TryParse(((TextBox)sender).Text, out num); if (success & num >= 0) { ((TextBox)sender).Text.Trim(); previousText = ((TextBox)sender).Text; } else { ((TextBox)sender).Text = previousText; ((TextBox)sender).SelectionStart = ((TextBox)sender).Text.Length; } } } } } 

ant就是这样。 如果你有很多文本框比我build议创build从TextBoxinheritance的CustomControl,所以你可以包装previousText和numericTB_TextChanged在一个单独的文件。

快乐的编码。

这是唯一需要的代码:

 void MyTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { e.Handled = new Regex("[^0-9]+").IsMatch(e.Text); } 

这只允许将数字input到文本框中。

要允许小数点或减号,可以将正则expression式更改为[^0-9.-]+

如果你不想写很多的代码来做一个基本的function(idk为什么人们做长方法),当你可以这样做:

  1. 添加命名空间:

     using System.Text.RegularExpressions; 
  2. 在Xaml中设置一个TextChanged属性:

     <TextBox x:Name="txt1" TextChanged="txt1_TextChanged"/> 
  3. 在WPF的txt1_TextChanged方法下,添加Regex.Replace

     private void txt1_TextChanged(object sender, TextChangedEventArgs e) { txt1.Text = Regex.Replace(txt1.Text, "[^0-9]+", ""); } 

我们可以对文本框更改的事件进行validation。 以下实现可防止除数字和小数点以外的按键input。

 private void textBoxNumeric_TextChanged(object sender, TextChangedEventArgs e) { TextBox textBox = sender as TextBox; Int32 selectionStart = textBox.SelectionStart; Int32 selectionLength = textBox.SelectionLength; String newText = String.Empty; int count = 0; foreach (Char c in textBox.Text.ToCharArray()) { if (Char.IsDigit(c) || Char.IsControl(c) || (c == '.' && count == 0)) { newText += c; if (c == '.') count += 1; } } textBox.Text = newText; textBox.SelectionStart = selectionStart <= textBox.Text.Length ? selectionStart : textBox.Text.Length; } 

这是使用MVVM来做这个非常简单和容易的方法。

绑定您的文本框与视图模型中的int属性,这将像gem工作…即使它会显示validation非整数input到文本框中。 XAML代码:

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

查看型号代码:

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

希望这可以帮助!

 e.Handled = (int)e.Key >= 43 || (int)e.Key <= 34; 

在预览文本框的keydown事件。

  Private Sub DetailTextBox_PreviewTextInput(ByVal sender As Object, ByVal e As System.Windows.Input.TextCompositionEventArgs) Handles DetailTextBox.PreviewTextInput If _IsANumber Then If Not Char.IsNumber(e.Text) Then e.Handled = True End If End If End Sub 

这是一个老问题,但是我正在为一个我正在开发的简单项目使用一个未绑定的框,所以我不能使用标准的绑定方法。 因此,我创build了一个简单的黑客机制,通过简单地扩展现有的TextBox控件,其他人可能会发现非常方便:

 namespace MyApplication.InterfaceSupport { public class NumericTextBox : TextBox { public NumericTextBox() : base() { TextChanged += OnTextChanged; } public void OnTextChanged(object sender, TextChangedEventArgs changed) { if (!String.IsNullOrWhiteSpace(Text)) { try { int value = Convert.ToInt32(Text); } catch (Exception e) { MessageBox.Show(String.Format("{0} only accepts numeric input.", Name)); Text = ""; } } } public int? Value { set { if (value != null) { this.Text = value.ToString(); } else Text = ""; } get { try { return Convert.ToInt32(this.Text); } catch (Exception ef) { // not numeric. } return null; } } } } 

显然,对于浮动types,你可能想把它parsing为一个浮点数等等。 原则适用。

然后在XAML文件中,您需要包含相关的名称空间:

 <UserControl x:Class="MyApplication.UserControls.UnParameterisedControl" [ Snip ] xmlns:interfaceSupport="clr-namespace:MyApplication.InterfaceSupport" > 

之后,您可以将其用作常规控件:

 <interfaceSupport:NumericTextBox Height="23" HorizontalAlignment="Left" Margin="168,51,0,0" x:Name="NumericBox" VerticalAlignment="Top" Width="120" > 

这是一个老问题,但在使用了一些解决scheme一段时间后,我开发了自己的MVVM设置。 请注意,它不像其他的一些dynamic一样,仍然允许用户input错误的字符,但它阻止了他们按下button,从而做任何事情。 当我不能执行操作的时候,我的主题就是灰色的button。

我有一个TextBox ,用户必须input要打印的文档页数:

 <TextBox Text="{Binding NumberPagesToPrint, UpdateSourceTrigger=PropertyChanged}"/> 

…这个绑定属性:

 private string _numberPagesToPrint; public string NumberPagesToPrint { get { return _numberPagesToPrint; } set { if (_numberPagesToPrint == value) { return; } _numberPagesToPrint = value; OnPropertyChanged("NumberPagesToPrint"); } } 

我也有一个button:

 <Button Template="{DynamicResource CustomButton_Flat}" Content="Set" Command="{Binding SetNumberPagesCommand}"/> 

用这个命令绑定:

 private RelayCommand _setNumberPagesCommand; public ICommand SetNumberPagesCommand { get { if (_setNumberPagesCommand == null) { int num; _setNumberPagesCommand = new RelayCommand(param => SetNumberOfPages(), () => Int32.TryParse(NumberPagesToPrint, out num)); } return _setNumberPagesCommand; } } 

然后是SetNumberOfPages()的方法,但是对于这个话题并不重要。 在某些情况下,某些解决scheme比其他解决scheme更好,所以我想我会分享这个解决scheme,以便与我处于类似情况的人可以使用它。 它在我的情况下效果很好,因为我不必将任何代码添加到视图的代码隐藏文件,它允许我使用Command属性来控制行为。

当检查数字值时,可以使用VisualBasic.IsNumeric函数

 PreviewTextInput += (s, e) => { e.Handled = !e.Text.All(char.IsDigit); }; 

在Wpf应用程序中,您可以通过处理TextChanged事件来处理这个事件:

 void arsDigitTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) { Regex regex = new Regex("[^0-9]+"); bool handle = regex.IsMatch(this.Text); if (handle) { StringBuilder dd = new StringBuilder(); int i = -1; int cursor = -1; foreach (char item in this.Text) { i++; if (char.IsDigit(item)) dd.Append(item); else if(cursor == -1) cursor = i; } this.Text = dd.ToString(); if (i == -1) this.SelectionStart = this.Text.Length; else this.SelectionStart = cursor; } } 

这里是一个WPF数字input库

它具有像NumberStylesRegexPattern属性进行validation。

子类WPF TextBox

的NuGet

在Windows窗体中很容易,您可以为KeyPress添加一个事件,并且一切都很容易。 但是,在WPF中,事件并不存在。 但是有一个更简单的方法。

WPF文本框有TextChanged事件,这是一般的一切,它包括粘贴,打字和任何可以提出你的想法。

所以你可以做这样的事情:

XAML:

 <TextBox name="txtBox1" ... TextChanged="TextBox_TextChanged"/> 

代码后面:

 private void TextBox_TextChanged(object sender, TextChangedEventArgs e) { string s = Regex.Replace(((TextBox)sender).Text, @"[^\d.]", ""); ((TextBox)sender).Text = s; } 

这也接受. ,如果你不需要它,只要从regex删除它就是@[^\d]

注意 :这个事件可以在许多文本框中使用,因为它使用了sender对象的文本。 你只写一次事件,并可以用它多个文本框。

这是我将用来获得接受数字和小数点的wpf文本框:

 class numericTextBox : TextBox { protected override void OnKeyDown(KeyEventArgs e) { bool b = false; switch (e.Key) { case Key.Back: b = true; break; case Key.D0: b = true; break; case Key.D1: b = true; break; case Key.D2: b = true; break; case Key.D3: b = true; break; case Key.D4: b = true; break; case Key.D5: b = true; break; case Key.D6: b = true; break; case Key.D7: b = true; break; case Key.D8: b = true; break; case Key.D9: b = true; break; case Key.OemPeriod: b = true; break; } if (b == false) { e.Handled = true; } base.OnKeyDown(e); } } 

把代码放在一个新的类文件中,添加

 using System.Windows.Controls; using System.Windows.Input; 

在文件的顶部并构build解决scheme。 numericTextBox控件将出现在工具箱的顶部。