带变化的数字文本框





3.00/5 (2投票s)
一个只接受格式化或未格式化数字以及后缀乘数的文本框。

引言
在我最近的一个项目中,我需要指定一个配额大小。对于生产环境,它总是可以是 GB,但为了测试目的,我想使用 MB 甚至 KB 的值。这让我想到了如何更轻松地输入这类信息,其中数字的大小可以作为数字的一部分来指定,就像浮点数的指数一样,只是更通用。所以,我又发明了一个数字文本框,但增加了一个额外的功能。这个文本框允许用户指定一组后缀字符串,每个字符串都有一个关联的乘数,这样你就可以在文本框中输入“1GB”,增强文本框的内部数值将返回 1,073,741,824。同样,输入“1.5 欧元”,截至目前,将返回 2.211555,即美元价值。
实现
这里有两个问题需要讨论。第一个是使用正则表达式求值器来限制文本框中可接受的值。第二个,当然是可选后缀的实现。
使用正则表达式验证文本框数据
我试图通过添加国际化功能使这个控件尽可能通用。因此,用于验证文本的正则表达式需要根据程序运行的区域设置动态创建。
每次文本框中的文本发生更改时,新字符串值都会与正则表达式进行验证。如果不匹配,则与文本框关联的数值将设置为 0。如果匹配,则将数字字符串转换为十进制值,该值将作为文本框的数值返回。我意识到这有点效率低下,因为它需要评估对文本框的每一次更改,但实际上,用户在单行文本框中输入的击键次数相当少,使得开销微不足道。优点是计算出的值可以立即显示,就像我在关联的演示程序中所做的那样。
我为美国地区使用的基本正则表达式是
^\s*([+-]?\s* (?: (?: (?:\d{1,3}[\,]) (?:\d{3}[\,])* (?:\d{3}) ) | \d+ |
(?=\.\d)) (?:\.\d*)? )\s* ([^\,\.\s\d].*)? \s*$
请注意,此正则表达式支持包含可选前导符号、可选小数分隔符和可选分组字符的数字,例如 -123,456.789,后面可以选择跟着任意后缀字符串。有效数字由可选符号后跟以下任意一项组成:
- 一个数字字符串,或
- 一组组(组大小由区域设置确定),其中最左边的组由 1 个或多个数字后跟一个分隔符组成;第二个组是可选的,由组大小数量的数字后跟一个分隔符组成,最右边的组由组大小数量的数字组成,后面可以选择跟着一个小数分隔符,再后面跟着零个或多个数字。
此处的国际化需要实时更改默认的组分隔符“,”、默认的小数分隔符“.”以及组大小(通常为 3)。您可以在源代码中查看详细信息。
在表达式的末尾,我添加了一个额外的表达式来匹配任何不以空格、分隔符字符或数字开头的字符串。此字符串从数字文本中提取,用于确定比例因子,即应用于字符串数值的乘数。
计算文本框的缩放数值
如果省略比例因子,则无需执行任何其他操作。如果指定了比例因子,我们将在下面讨论的集合中查找比例因子,然后简单地将文本框的数值乘以与比例因子关联的数值。请注意,搜索是蛮力搜索。它可以实现为哈希表,但总的来说,对于这种类型的控件要使用的比例因子的数量非常少,顺序搜索通常是最优的。
检索比例因子
比例因子的名称和关联值存储在名称-值对的集合中,其中名称是toUpperCase的后缀,十进制值是指定相关名称时要使用的乘数。
我创建了一个强类型集合类,它继承自 CollectionBase。这样做允许我在设计时修改我的 UserScaleItems 属性。 `NVPCollection` 类中的每个项都是 NVP 类的成员,该类仅包含两个属性:`string` 名称和十进制值。
通过迭代集合来检索比例因子的十进制值,寻找与比例因子名称匹配的项,例如:
foreach (NVP nvp in scaleItems)
{
if (nvp.Name == scaleSuffix)
{
numericValue *= nvp.DecimalValue;
goodValue = true;
}
}
存储比例因子
比例因子数据存储在 `scaleItems` 中,它是 `NVPCollection` 类的一个实例,可以在设计时输入,也可以通过几种运行时方式输入。由于我使用了一个强类型集合类来存储名称-值对,并将其作为 `UserScaleItems` 属性公开,因此用户可以单击 `UserScaleItems` 后的省略号来向集合添加一组名称-值对。请注意,一旦以这种方式添加,它们就不会被任何运行时设置覆盖。一旦名称被输入到集合中,所有后续相同名称的添加都将被忽略。

可以通过几种方式在运行时输入名称-值对
// Here are two ways to add suffixes at run-time. Note that run-time items
// will be ignored if the item name already exists in the collection, e.g.,
// from a development-time entry:
dtb.UserScaleItems.Add("+TAX", 1.0875M);
dtb.LoadSuffixes("%", ".01", "Euro",
"1.47437", "Yen", "0.009168");
// Here is a quick way to load common, built-in suffixes:
dtb.LoadDefaultSuffixes();
/* The above method is equivalent to the following:
dtb.LoadSuffixes("B", "1M",
"M", "1000",
"MM", (1000M * 1000M).ToString(),
"MMM", (1000M * 1000M 1000M).ToString(),
"KB", "1024",
"MB", (1024M * 1024M).ToString(),
"GB", (1024M * 1024M * 1024M).ToString(),
"TB", (1024M * 1024M * 1024M * 1024M).ToString());
*/
附加的演示允许您输入数字文本(包括组分隔符),后面可以选择跟着上述后缀之一,或设计时后缀之一(您可以通过单击 `UserScaleItems` 省略号如上所述进行设置)。我主要使用它来输入大字节值,而不必事先乘以适当的 1024 的幂。但是,正如上面提到的,您可以下载当前的 FX 符号和汇率,并允许用户直接以任何货币输入数据,而不必有一个单独的下拉列表框或附加文本框来指定适当的货币。
在您的项目中使用控件
首先,编译控件并将生成的 DLL 放入您选择的文件夹中,最好是包含可重用程序集的文件夹。或者,您也可以直接从提供的 zip 文件中复制 `DecimalTextBox.dll` 和 `DecimalTextBox.xml` 文件。
打开一个项目并显示工具箱。转到“通用控件”部分,右键单击,然后选择“选择项”。在“选择工具箱项”对话框中,按“浏览”按钮,导航到包含 `DecimalTextBox.dll` 的文件夹,然后为您的项目选择它。现在,您可以使用此控件输入数值并进行自动转换。
历史
- 版本 1.0.7.5 – 2008 年 2 月 26 日
- 版本 1.0.8.0 – 2009 年 1 月 1 日 - 此版本添加了一个条件,允许生成一个区分大小写的后缀版本。