Поведение WPF не работает должным образом
Я пытался создать поведение wpf. Что я делаю, это ищу нажатия клавиш OemPeriod
,Decimal
, backspace
а также delete
, Если строка в текстовом поле 101.55
и пользователь нажимает Decimal или OemPeriod, перемещая курсор назад к 10, он удалит строку 1 после 10, и строка станет 10.55
,
Эта часть работает как задумано. но настоящая проблема с back (backspace)
а также Delete
ключи.
Если текст в текстовом поле 10.55
и курсор находится после .
(индекс каретки = 2) и пользователь нажимает клавишу Backspace, каретка сдвигает свою позицию на -1(перед десятичной дробью) и добавляет 55
после позиции каретки и текст становится 1055.00
и то же самое происходит для Delete
ключ.
текст отформатирован с использованиемStringFormat={}{0:#.00}
Вот мой код, может кто-нибудь сказать мне, что не так?
public class DecimalWatchingBehaviour : Behavior<UIElement>
{
protected override void OnAttached()
{
base.OnAttached();
TextBox t = AssociatedObject as TextBox;
if (t != null)
{
t.PreviewKeyUp += shiftCaretPosition;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
TextBox t = AssociatedObject as TextBox;
if (t != null)
{
t.PreviewKeyUp -= shiftCaretPosition;
}
}
private void shiftCaretPosition(object sender, KeyEventArgs args)
{
TextBox t = sender as TextBox;
if (t == null) return;
string txt = t.Text;
if (!txt.Contains("."))
{
return;
}
int index = txt.IndexOf(".", StringComparison.Ordinal);
int caretIndex = t.CaretIndex;
if ((args.Key == Key.OemPeriod || args.Key == Key.Decimal))
{
t.Text = t.Text.Remove(t.CaretIndex, index);
t.CaretIndex = t.Text.IndexOf(".", StringComparison.Ordinal) + 1;
} else if (args.Key == Key.Back && txt.Substring(caretIndex < index ? caretIndex : index,
caretIndex < index ? index - caretIndex : caretIndex - index) == ".")
{
t.CaretIndex = index - 1;
} else if (args.Key == Key.Delete && txt.Substring(caretIndex < index ? caretIndex : index,
caretIndex < index ? index - caretIndex : caretIndex - index) == ".")
{
t.CaretIndex = index + 1;
}
}
}
Вот объявление пространства имен xaml
xmlns:behaviour="clr-namespace:Utils.UI.Input.Behaviour;assembly=Utils"
<UserControl.Resources>
<behaviour:DecimalWatchingBehaviour x:Key="decimalWatchingBehaviour" />
</UserControl.Resources>
И текстовое поле в xaml
<TextBox
Margin="5"
Text="{Binding NewBatch.Cess,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
StringFormat={}{0:#.00}}" >
<i:Interaction.Behaviors>
<behaviour:DecimalWatchingBehaviour/>
</i:Interaction.Behaviors>
</TextBox>
1 ответ
Вы можете обратиться к следующему простому фрагменту кода обработчика событий, который предоставляет аналогичные функциональные возможности, а именно: ограничение WPF TextBox1
ввод для числовой записи и некоторых специальных клавиш:
// PreviewKeyDown event proc:
// only numeric and some special keys input allowed
TextBox1.PreviewKeyDown += (s, e) =>
{
// intercept modifier "SHIFT" key
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{ e.Handled = true; }
// cast e.Key to int
int _intKey = (int)e.Key;
// allow the following key
if (e.Key == Key.Back ||
e.Key == Key.Delete ||
e.Key == Key.Enter ||
e.Key == Key.Return ||
e.Key == Key.Tab ||
e.Key == Key.OemPeriod ||
e.Key == Key.OemComma ||
e.Key == Key.Decimal ||
e.Key == Key.Left ||
e.Key == Key.Right ||
(_intKey <= 43 && _intKey >= 34) ||
(_intKey <= 84 && _intKey >= 73))
{
// the rest of the event handling code
return;
}
else e.Handled = true;
};
где TextBox1
целевой элемент управления TextFox WPF Нет необходимости в дополнительном XAML или коде позади.
Надеюсь, что это может помочь.