Windows 窗体中的十进制文本框

Decimal Textbox in Windows Forms

提问人:Tigraine 提问时间:10/28/2008 更新时间:9/15/2018 访问量:15782

问:

我正在做一个 Financial Winforms 应用程序,并且在控件方面遇到了一些问题。

我的客户需要到处插入十进制值(价格、折扣等),我想避免一些重复验证。

因此,如果不是因为遮罩的焦点和长度,我立即尝试了适合我需求的 MaskedTextBox(带有像“€ 00000.00”这样的遮罩)。

我无法预测我的客户将在应用程序中输入多大的数字。

我也不能指望他以 00 开头所有内容来达到逗号。一切都应该对键盘友好。

我是否遗漏了某些内容,或者根本没有办法(除了编写自定义控件之外)使用标准 Windows 窗体控件实现此目的?

WinForms 控件 输入 Maded-TextBox

评论


答:

5赞 Nick 10/28/2008 #1

您将需要一个自定义控件。只需在控件上捕获 Validating 事件,并检查字符串输入是否可以解析为小数。

评论

0赞 Tigraine 10/28/2008
谢谢。。这给我留下了下一个挑战。创建自定义控件 gg ..
1赞 Rockcoder 10/28/2008 #2

MSDN:Windows 窗体中的用户输入验证

3赞 nportelli 10/28/2008 #3

我认为您不需要自定义控件,只需为验证事件编写一个十进制验证方法,并将其用于您需要验证的所有位置。不要忘记包含 NumberFormatInfo,它将处理逗号和 numebr 符号。

评论

0赞 Joel Coehoorn 10/28/2008
准备好一个自定义控件将为他节省一堆样板代码,他需要将它连接起来:这是一件好事。
6赞 Abel Gaxiola 10/28/2008 #4

这两个覆盖的方法为我做到了(免责声明:此代码尚未投入生产。您可能需要修改)

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (!char.IsNumber(e.KeyChar) & (Keys)e.KeyChar != Keys.Back 
            & e.KeyChar != '.')
        {
            e.Handled = true;
        }

        base.OnKeyPress(e);
    }

    private string currentText;

    protected override void OnTextChanged(EventArgs e)
    {
        if (this.Text.Length > 0)
        {
            float result;
            bool isNumeric = float.TryParse(this.Text, out result);

            if (isNumeric)
            {
                currentText = this.Text;
            }
            else
            {
                this.Text = currentText;
                this.Select(this.Text.Length, 0);
            }
        }
        base.OnTextChanged(e);
    }

评论

0赞 Tigraine 10/29/2008
多谢。我用一个自定义控件实现了这个,并在博客上写了关于它的文章:tigraine.at/2008/10/28/decimaltextbox-for-windows-forms
0赞 clamchoda 9/15/2018
很好的答案,但没有复制粘贴支持(阻止 ctrl + v/c)
0赞 clamchoda 9/15/2018
简单的解决方案是删除覆盖并将以下内容添加到顶部以清除字符。OnKeyPressOnTextChangedthis.Text = Regex.Replace(this.Text, "[^.0-9]", "");
0赞 madmaniac 3/16/2015 #5

您只需要让数字和十进制符号通过,并避免使用双十进制符号。另外,这会自动在起始十进制数之前添加一个 0。

public class DecimalBox : TextBox
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (e.KeyChar == ',')
        {
            e.KeyChar = '.';
        }

        if (!char.IsNumber(e.KeyChar) && (Keys)e.KeyChar != Keys.Back && e.KeyChar != '.')
        {
            e.Handled = true;
        }

        if(e.KeyChar == '.' )
        {
            if (this.Text.Length == 0)
            {
                this.Text = "0.";
                this.SelectionStart = 2;
                e.Handled = true;
            }
            else if (this.Text.Contains("."))
            {
                e.Handled = true;
            }
        }

        base.OnKeyPress(e);
    }
}
0赞 clamchoda 9/15/2018 #6

另一种方法是阻止您不想要的内容,并在完成后进行格式化。

class DecimalTextBox : TextBox
{
    // Handle multiple decimals
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (e.KeyChar == '.')
            if (this.Text.Contains('.'))
                e.Handled = true;

        base.OnKeyPress(e);
    }

    // Block non digits
    // I scrub characters here instead of handling in OnKeyPress so I can support keyboard events (ctrl + c/v/a)
    protected override void OnTextChanged(EventArgs e)
    {
        this.Text = System.Text.RegularExpressions.Regex.Replace(this.Text, "[^.0-9]", "");
        base.OnTextChanged(e);
    }

    // Apply our format when we're done
    protected override void OnLostFocus(EventArgs e)
    {
        if (!String.IsNullOrEmpty(this.Text))
            this.Text = string.Format("{0:N}", Convert.ToDouble(this.Text));

        base.OnLostFocus(e);
    }


}