WPF TextBox输入十进制值 [英] WPF TextBox to enter decimal values

查看:89
本文介绍了WPF TextBox输入十进制值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有任何体面的方法来获取绑定到十进制值的WPF控件?

Is there any decent way to get a WPF control which is bound to a decimal value?

何时我只是将 TextBox DataGridTextColumn 绑定到十进制,数据输入是个问题。

When I just bind the TextBox or DataGridTextColumn to a decimal, data entry is a problem.

<TextBox Text="{Binding MyDecimal, UpdateSourceTrigger=PropertyChanged, 
    ValidatesOnDataErrors=True}"/>

当我尝试在此 TextBox中输入 0,5时结果是 5。几乎根本不可能输入 0,5(除了输入1,5并用 0代替 1)。

When I try to enter "0,5" in this TextBox I'll get "5" as a result. It is nearly impossible to enter "0,5" at all (apart from entering 1,5 and replacing the "1" with a "0").

当我使用 StringFormat ,数据输入只会稍微改善:

When I use StringFormat, data entry is only slightly improved:

<TextBox Text="{Binding MyDecimal, StringFormat=F1, UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=True}"/>

现在,当我尝试输入 0,5时,我将以 0, 5,0,这仍然是错误的,但至少我可以毫不费力地删除结尾的,0。

Now, when I try to enter "0,5" I'll end up with "0,5,0", which still is wrong but at least I can remove the trailing ",0" without much difficulty.

仍然,输入 decimal使用WPF的类型非常尴尬,因为这些 TextBox es 非常容易出现数据输入错误,这是真实的痛苦尤其是价值观!

Still, entering decimal types using WPF is very awkward, because these TextBoxes are very prone to data entry errors, which is a real pain especially for values!

那么我应该在WPF中使用十进制数据输入什么?还是Microsoft不支持十进制数据?

So what am I supposed to use for decimal data entry in WPF? Or does Microsoft not support decimal data??

推荐答案

我目前将此行为用于数字和十进制输入:

I currently use this behavior for digital and decimal input:

public class TextBoxInputBehavior : Behavior<TextBox>
{
    const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint |
                                               NumberStyles.AllowThousands |
                                               NumberStyles.AllowLeadingSign;
    public TextBoxInputBehavior()
    {
        this.InputMode = TextBoxInputMode.None;
        this.JustPositivDecimalInput = false;
    }

    public TextBoxInputMode InputMode { get; set; }


    public static readonly DependencyProperty JustPositivDecimalInputProperty =
     DependencyProperty.Register("JustPositivDecimalInput", typeof(bool),
     typeof(TextBoxInputBehavior), new FrameworkPropertyMetadata(false));

    public bool JustPositivDecimalInput
    {
        get { return (bool)GetValue(JustPositivDecimalInputProperty); }
        set { SetValue(JustPositivDecimalInputProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput;
        AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown;

        DataObject.AddPastingHandler(AssociatedObject, Pasting);

    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput;
        AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown;

        DataObject.RemovePastingHandler(AssociatedObject, Pasting);
    }

    private void Pasting(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(typeof(string)))
        {
            var pastedText = (string)e.DataObject.GetData(typeof(string));

            if (!this.IsValidInput(this.GetText(pastedText)))
            {
                System.Media.SystemSounds.Beep.Play();
                e.CancelCommand();
            }
        }
        else
        {
            System.Media.SystemSounds.Beep.Play();
            e.CancelCommand();
        }
     }

     private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e)
     {
        if (e.Key == Key.Space)
        {
            if (!this.IsValidInput(this.GetText(" ")))
            {
                System.Media.SystemSounds.Beep.Play();
                e.Handled = true;
            }
        }
     }

     private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e)
     {
        if (!this.IsValidInput(this.GetText(e.Text)))
        {
            System.Media.SystemSounds.Beep.Play();
            e.Handled = true;
        }
     }

     private string GetText(string input)
     {
        var txt = this.AssociatedObject;

        int selectionStart = txt.SelectionStart;
        if (txt.Text.Length < selectionStart) 
            selectionStart = txt.Text.Length;

        int selectionLength = txt.SelectionLength;
        if (txt.Text.Length < selectionStart + selectionLength) 
            selectionLength = txt.Text.Length - selectionStart;

        var realtext = txt.Text.Remove(selectionStart, selectionLength);

        int caretIndex = txt.CaretIndex;
        if (realtext.Length < caretIndex) 
            caretIndex = realtext.Length;

        var newtext = realtext.Insert(caretIndex, input);

        return newtext;
     }

     private bool IsValidInput(string input)
     {
        switch (InputMode)
        {
            case TextBoxInputMode.None:
                return true;
            case TextBoxInputMode.DigitInput:
                return CheckIsDigit(input);

            case TextBoxInputMode.DecimalInput:
                decimal d;
                //wen mehr als ein Komma
                if (input.ToCharArray().Where(x => x == ',').Count() > 1)
                    return false;


                if (input.Contains("-"))
                {
                     if (this.JustPositivDecimalInput) 
                        return false;


                     if (input.IndexOf("-",StringComparison.Ordinal) > 0) 
                          return false;

                      if(input.ToCharArray().Count(x=>x=='-') > 1)
                          return false;

                        //minus einmal am anfang zulässig
                       if (input.Length == 1) 
                           return true;
                    }

                    var result = decimal.TryParse(input, validNumberStyles, CultureInfo.CurrentCulture, out d);
                    return result;



            default: throw new ArgumentException("Unknown TextBoxInputMode");

        }
        return true;
     }

     private bool CheckIsDigit(string wert)
     {
        return wert.ToCharArray().All(Char.IsDigit);
     }
}

 public enum TextBoxInputMode
 {
  None,
  DecimalInput,
  DigitInput
  }

XAML的用法如下:

The XAML usage looks like this:

<TextBox Text="{Binding Sum}">
    <i:Interaction.Behaviors>
        <Behaviors:TextBoxInputBehavior InputMode="DecimalInput"/>
    </i:Interaction.Behaviors>
</TextBox>

这篇关于WPF TextBox输入十进制值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆