Создайте текстовый блок WPF, который принимает только числа
Я хотел бы создать TextBox, который принимает только числовые значения в определенном диапазоне.
Каков наилучший способ реализовать такой TextBox?
Я думал о выводе TextBox и переопределении проверки и принуждения TextProperty. Однако я не уверен, как это сделать, и я понимаю, что получение 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)
Некоторые из предлагаемых решений, вероятно, лучше, но для простой функциональности я нуждался в этом решении, которое было бы самым простым и быстрым в реализации, достаточным для моих нужд.
Ответы
Ответ 1
Большинство реализаций, которые я видел до сих пор, используют PreviewTextInput для реализации правильного поведения маски. Этот один наследует от TextBox и этот использует прилагаемые свойства. Оба используют .Net MaskedTextProvider, чтобы обеспечить правильное поведение маски, но если вам просто нужно простое текстовое поле с номерами, вам не нужно этот класс.
Ответ 2
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<TextChange>(0);
int iAddedLength = textChange.AddedLength;
int iOffset = textChange.Offset;
textBox.Text = textBox.Text.Remove(iOffset, iAddedLength);
}
}
Ответ 3
По моему скромному мнению, лучший способ выполнить это требование - использовать только событие OnTextChanged
, потому что он может обрабатывать цифру от нажатия клавиши, а также иметь возможность обрабатывать Copy + Paste из буфера обмена. Я надеюсь, что мой код 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
Ответ 4
В целом лучше всего использовать метод переопределения OnKeyPressed
для текстового поля. Вот код для переопределения с использованием статического метода Char IsDigit
.
if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar)) e.Handled = true;
Это все, что вам действительно нужно делать.
Ответ 5
Это был бы мой предпочтительный подход:
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;
}
}