来自 TextBox 类的货币掩码文本框
这是一个有用的控件,它使用货币符号、千位分隔符和小数分隔符来掩码输入文本。
引言
在某些应用程序中,我们需要在 TextBox 中显示带有某种掩码的输入文本,例如,货币掩码,以便更容易阅读和理解。在我的情况下,我需要在输入文本后,另外加上货币符号。为此,我决定开发一个继承自原始 TextBox 控件的自定义控件,并实现一些新成员,以便该控件能够验证并显示带有我们所需货币掩码的输入文本。
背景
下面是简要说明...
TextBox (System.Windows.Forms.TextBox)
TextBox 控件是 WinForms 应用程序中最基本且最常用的控件之一,它允许用户输入文本以与应用程序进行交互。它具有基本行为和成员,使我们无需向控件添加任何内容即可立即使用它。
基于 TextBox 控件,我们将开发一个 TextBox,它可以将我们的输入文本用货币格式进行掩码,包括我们想要的货币符号。
继承
继承是一种通过创建具有基于先前创建对象特质和行为的对象来划分和重用代码的方法。
继承允许我们通过利用 TextBox 等简单控件的基本行为来使用它们,并使我们能够通过添加新成员来控制我们需要的某些行为来改进控件。
在 Visual C# 中,我们可以像这样编写一个继承自 TextBox 的类定义
public partial class customTextBox : System.Windows.Forms.TextBox
方法重写
这是一项功能,允许子类提供其父类已提供的某个方法的特定实现。
例如,在 Visual C# 中,我们可以通过编写以下代码来重写父类的方法
protected override void OnLostFocus(EventArgs e)
{
    this.Text = formatText();
    base.OnLostFocus(e);
}
开发
这里是对 currencyTextBox 代码的解释
currencyTextBox 控件库
JRINCCustomControls 控件库仅包含 currencyTextBox 控件,您可以将其添加到 Visual Studio 的工具箱中

…或者可以直接在您的项目中将其作为 DLL 组件引用

演示项目
演示项目将向您展示如何在 WinForms 项目中实现 currencyTextBox 控件,您可以在其中测试关于该控件的任何内容。

代码
现在我将解释我为新文本框添加的各种成员以及它们的工作原理。
在 JRINCCustomControls 项目的 currencyTextBox 类中,有各种自定义成员帮助我们实现为输入文本添加货币掩码的目标。它们是:
公共属性
WorkingText (public string)
这是一个只读属性,包含我们的“工作文本”。这意味着它包含用户在 TextBox 中输入的精确内容,即没有任何掩码或格式化的文本。
定义
private string _workingText;
public string WorkingText
{
    get { return _workingText; }
    private set { _workingText = value; }
}
PreFix (public string)
这是一个公共属性,可以进行赋值和检索。它必须包含我们希望前置于输入文本的符号或货币符号。如果为空,则在掩码文本中不使用前缀。它可以在设计时通过属性窗口进行赋值。
默认值:空。

定义
private string _preFix;
 
/// <summary>
/// Contains the prefix that preceed the inputted text.
/// </summary>
public string PreFix
{
    get { return _preFix; }
    set { _preFix = value; }
}
ThousandsSeparator (public char)
这是一个公共属性,可以进行赋值和检索。它必须包含我们希望输入文本在掩码时显示的千位分隔符。如果为空,则在掩码文本中不使用千位分隔符。它可以在设计时通过属性窗口进行赋值。
默认值:','。

定义
private char _thousandsSeparator = ',';
/// <summary>
/// Contains the separator symbol for thousands.
/// </summary>
public char ThousandsSeparator
{
    get { return _thousandsSeparator; }
    set { _thousandsSeparator = value; }
  
}
DecimalsSeparator (public char)
这是一个公共属性,可以进行赋值和检索。它必须包含我们希望输入文本在掩码时显示的小数分隔符。如果为空,则在掩码文本中不使用小数分隔符。它可以在设计时通过属性窗口进行赋值。
默认值:'。'。

定义
private char _decimalsSeparator = '.';
/// <summary>
/// Contains the separator symbol for decimals.
/// </summary>
public char DecimalsSeparator
{
    get { return _decimalsSeparator; }
    set { _decimalsSeparator = value; }
}
DecimalPlaces (public int)
这是一个公共属性,可以进行赋值和检索。它必须包含我们希望输入文本在掩码时显示的小数值的总位数。最小值为 0。它可以在设计时通过属性窗口进行赋值。
默认值:2。

定义
private int _decimalPlaces = 2;
/// <summary>
/// Indicates the total places for decimal values.
/// </summary>
public int DecimalPlaces
{
    get { return _decimalPlaces; }
    set { _decimalPlaces = value; }
}
公共方法
formatText (public method) 返回 string
它根据所需的规范格式化输入的文本。返回一个带有掩码文本的字符串。
定义
/// <summary>
/// Formats the entered text.
/// </summary>
/// <returns></returns>
public string formatText()
{
    this.WorkingText = this.Text.Replace(
      (_preFix != "") ? _preFix : " ", String.Empty).Replace(
      (_thousandsSeparator.ToString() != "") ? 
        _thousandsSeparator.ToString() : " ", String.Empty).Replace(
      (_decimalsSeparator.ToString() != "") ? 
        _decimalsSeparator.ToString() : " ", String.Empty).Trim();
    int counter = 1;
    int counter2 = 0;
    char[] charArray = this.WorkingText.ToCharArray();
    StringBuilder str = new StringBuilder();
    for (int i = charArray.Length - 1; i >= 0; i--)
    {
        str.Insert(0, charArray.GetValue(i));
        if (this.DecimalPlaces == 0 && counter == 3)
        {
            counter2 = counter;
        }
        
        if (counter == this.DecimalPlaces && i > 0)
        {
            if (_decimalsSeparator != Char.MinValue)
                str.Insert(0, _decimalsSeparator);
            counter2 = counter + 3;
        }
        else if (counter == counter2 && i > 0)
        {
            if (_thousandsSeparator != Char.MinValue)
                str.Insert(0, _thousandsSeparator);
            counter2 = counter + 3;
        }
        counter = ++counter;
    }
    return (this._preFix != "" && str.ToString() != "") ? 
       _preFix + " " + str.ToString() : 
       (str.ToString() != "") ? str.ToString() : "";
}
受保护的重写方法
OnLostFocus (protected override method)
此方法允许 currencyTextBox 将格式化后的文本加载到 Text 属性。它执行 formatText 方法,然后继续执行 OnLostFocus 方法的原始实现。
定义
protected override void OnLostFocus(EventArgs e)
{
    this.Text = formatText();
    base.OnLostFocus(e);
}
OnGotFocus (protected override method)
此方法允许 currencyTextBox 将工作文本加载到 Text 属性。在这种状态下,控件处于编辑模式(请参阅上面的 WorkingText 属性定义)。之后,它继续执行 OnGotFocus 方法的原始实现。
定义
protected override void OnGotFocus(EventArgs e)
{
    this.Text = this.WorkingText;
    base.OnGotFocus(e);
}
OnKeyPress (protected override method)
此方法提供了一些验证,以确保输入到 TextBox 的值仅为数字。验证后,它执行 OnKeyPress 方法的原始实现。
定义
protected override void OnKeyPress(KeyPressEventArgs e)
{
    if (!Char.IsDigit(e.KeyChar))
    {
        if (!(e.KeyChar == Convert.ToChar(Keys.Back)))
            e.Handled = true;
    }
    base.OnKeyPress(e);
}
结论
我们可以改进 TextBox 这样的控件的特性非常多,我们可以做的最重要的事之一就是始终寻找改进它的方法,并通过添加像 CurrencyTextBox 这样的可重用组件来使其更易于维护。我希望它能像帮助我一样帮助您。




