具有StringFormat N2和十进制绑定奇怪问题的WPF自定义数字文本框

时间:2019-02-24 16:06:59

标签: c# wpf binding textbox string-formatting

我创建了下面的文本框,只接受可空的十进制数字。 当用户按下小数点分隔符时,光标跳至小数点。 我还创建了一个转换器,只是将空字符串修改为null。

它工作正常,但是在999.999.999,99之后,会触发一些奇怪的功能。当我尝试设置另一个数字时,光标跳到文本框中的随机位置,有时而不是按下的数字会在末尾添加零(0)。

这是我的代码, 文本框:

    public class NumericTextBox : TextBox
{
    char decimalSeperator;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        decimalSeperator = Convert.ToChar(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator);
        DataObject.AddPastingHandler(this, PasteHandler);

        this.KeyUp += NumericTextBox_KeyUp;
        this.PreviewKeyDown += NumericTextBox_PreviewKeyDown;
        this.PreviewTextInput += NumericTextBox_PreviewTextInput;
    }

    void NumericTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        if (!e.Text.IsDigitsOnly())
            e.Handled = true;
    }

    void NumericTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        HandleWhiteSpace(e);
    }

    void NumericTextBox_KeyUp(object sender, KeyEventArgs e)
    {
        if (IsDecimalSeperator(e))
        {
            if (TextExists() && HasDecimalSeperator())
                Select(Text.IndexOf(decimalSeperator) + 1, 0);
        }
    }

    void PasteHandler(object sender, DataObjectPastingEventArgs e)
    {
        e.CancelCommand();
    }

    void HandleWhiteSpace(KeyEventArgs e)
    {
        if (e.Key == Key.Space)
            e.Handled = true;
    }

    bool TextExists()
    {
        return !String.IsNullOrEmpty(Text) && Text.Length > 0;
    }

    bool IsDecimalSeperator(KeyEventArgs e)
    {
        return e.Key == Key.Decimal || e.Key == Key.OemComma;
    }

    bool HasDecimalSeperator()
    {
        return Text.IndexOf(decimalSeperator) > 0;
    }
}

IsDigitsOnly扩展名:

public static class StringExtensions
{
    public static bool IsDigitsOnly(this string str)
    {
        foreach (char c in str)
            if (c < '0' || c > '9')
                return false;

        return true;
    }
}

转换器:

public class EmptyStringToNullNumericConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value as string == string.Empty)
            value = null;

        return value;
    }
}

和我的XAML:

<cc:NumericTextBox Grid.Row="8" Text="{Binding Cost, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat='N2', Converter={StaticResource EmptyStringToNullNumericConverter}}"/>

“费用”属性是可为空的十进制。

0 个答案:

没有答案