WPF 行为无法正常工作

WPF behaviour not working properly

我试图创建一个 wpf behaviour.What 我所做的是寻找击键 OemPeriodDecimalbackspacedelete。如果文本框中的字符串是 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 或代码隐藏。

希望这可能有所帮助。