创建只接受数字的WPF TextBox

我想创建一个只接受特定范围内的数值的TextBox。 实现此类TextBox的最佳方法是什么?

我想到了派生TextBox并覆盖TextProperty的validation和强制。 但是,我不知道如何做到这一点,我知道通常不推荐导出WPF控件。


编辑:
我需要的是一个非常基本的文本框,可以过滤掉所有不是数字的按键。 实现它的最简单方法是处理TextBox.PreviewTextInput事件:

private void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { int result; if (!validateStringAsNumber(e.Text,out result,false)) { e.Handled = true; } } 

(validateStringAsNumber是我主要使用Int.TryParse的函数)

一些建议的解决方案可能更好,但是对于我需要的简单function,这个解决方案是最简单,最快速的,同时满足我的需求。

到目前为止,我见过的大多数实现都使用PreviewTextInput事件来实现正确的掩码行为。 这个inheritance自TextBox, 这个使用附加属性。 两者都使用.Net的MaskedTextProvider来提供正确的掩码行为,但是如果你只想要一个简单的“仅限数字”文本框,则不需要这个类。

 private void txt_TextChanged(object sender, TextChangedEventArgs e) { TextBox textBox = sender as TextBox; int iValue = -1; if (Int32.TryParse(textBox.Text, out iValue) == false) { TextChange textChange = e.Changes.ElementAt(0); int iAddedLength = textChange.AddedLength; int iOffset = textChange.Offset; textBox.Text = textBox.Text.Remove(iOffset, iAddedLength); } } 

在我看来,满足这个要求的最好方法是只使用OnTextChanged事件,因为它可以处理按键的数字,也可以处理剪贴板中的复制+粘贴。 我希望下面显示的VB代码能够对此有所了解。

 Private Sub NumericBox_TextChanged(sender As Object, e As TextChangedEventArgs) Handles Me.TextChanged Dim Buffer As New StringBuilder Dim Index As Integer = Me.SelectionStart For Each C In Me.Text If Char.IsDigit(C) Then Buffer.Append(C) ElseIf Me.SelectionStart > Buffer.Length Then Index -= 1 End If Next Me.Text = Buffer.ToString Me.SelectionStart = Index End Sub 

总体上最好的原因是为文本框使用覆盖方法OnKeyPressed 。 以下是使用静态Char方法IsDigit的覆盖代码。

 if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar)) e.Handled = true; 

这就是你真正需要做的。

这将是我的首选方法:

 private void yearTxt_PreviewKeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.D0: case Key.D1: case Key.D2: case Key.D3: case Key.D4: case Key.D5: case Key.D6: case Key.D7: case Key.D8: case Key.D9: case Key.NumLock: case Key.NumPad0: case Key.NumPad1: case Key.NumPad2: case Key.NumPad3: case Key.NumPad4: case Key.NumPad5: case Key.NumPad6: case Key.NumPad7: case Key.NumPad8: case Key.NumPad9: case Key.Back: break; default: e.Handled = true; break; } }