WPF 行为无法正常工作
WPF behaviour not working properly
我试图创建一个 wpf behaviour.What 我所做的是寻找击键 OemPeriod
、Decimal
、backspace
和 delete
。如果文本框中的字符串是 101.55
,并且用户通过将光标移回 10 来按下 Decimal 或 OemPeriod,它将删除 10 之后的字符串 1,并且该字符串将变为 10.55
。
该部分按预期工作。但真正的问题在于 back (backspace)
和 Delete
键。
如果文本框中的文本是 10.55
并且光标位于 .
之后(插入符号索引 = 2)并且用户按下退格键,则插入符号将其位置移动 -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>
您可以参考以下简单的事件处理程序代码片段,它提供了类似的功能,即:将 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
是感兴趣的目标 WPF TextBox 控件。不需要任何额外的 XAML 或代码隐藏。
希望这可能有所帮助。
我试图创建一个 wpf behaviour.What 我所做的是寻找击键 OemPeriod
、Decimal
、backspace
和 delete
。如果文本框中的字符串是 101.55
,并且用户通过将光标移回 10 来按下 Decimal 或 OemPeriod,它将删除 10 之后的字符串 1,并且该字符串将变为 10.55
。
该部分按预期工作。但真正的问题在于 back (backspace)
和 Delete
键。
如果文本框中的文本是 10.55
并且光标位于 .
之后(插入符号索引 = 2)并且用户按下退格键,则插入符号将其位置移动 -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>
您可以参考以下简单的事件处理程序代码片段,它提供了类似的功能,即:将 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
是感兴趣的目标 WPF TextBox 控件。不需要任何额外的 XAML 或代码隐藏。
希望这可能有所帮助。