C# 数字字段控件
数字字段控件的抽象基类。

引言
在创建了 .NET Framework 的 IP 地址控件 之后,我将学到的经验应用于创建一个抽象控件。此控件可以轻松配置,以允许输入任何由数字字段集合组成的值,例如 IP 地址、带端口的 IP 地址、IPv6 地址、MAC 地址、电话号码或社会安全号码。
背景
FlexFieldControl
是一个基于 UserControl
的抽象类,它聚合了 n 个 FieldControl
类型的控件和 n+1 个 SeparatorControl
类型的控件。这些控件以交替的方式水平排列,从 SeparatorControl
开始。下面是默认 FlexFieldControl
控件的图像,其中高亮显示了聚合的控件。

默认情况下,FlexFieldControl
包含三个 FieldControl
和四个 SeparatorControl
。按照下面的 API,下面是一个如何通过仅十行代码来扩展 FlexFieldControl
以创建新控件 MACAddressControl
的示例。
Using the Code
一旦包含 FlexFieldControl
的库(FlexFieldControlLib.dll)构建完成,请将该 DLL 添加到您的 Windows Forms 项目的引用中。FlexFieldControl
被定义为 abstract
;它不会出现在 Windows Forms 设计器的工具箱中。但是,任何基于 FlexFieldControl
的控件都会出现。
公共实例属性
AutoHeight
- 获取或设置一个值,该值指示控件是否根据当前字体和边框自动垂直调整大小。默认值为true
Blank
- 获取一个值,该值指示控件中的所有字段是否为空BorderStyle
- 获取或设置控件的边框样式。默认值为BorderStyle.Fixed3D
FieldCount
- 获取或设置控件中的字段数量。默认值为3
,最小值为1
。设置此值会重置每个字段和分隔符到其默认状态。ReadOnly
- 获取或设置一个值,该值指示控件的内容是否可以更改。Text
- 获取或设置控件的文本。
公共实例方法
AddCedeFocusKey
- 为一个字段添加一个特定的按键,该按键会将焦点转移到控件中的下一个字段。默认情况下,[空格键] 会为任何非空的字段转移焦点。Clear
- 清除控件中所有字段的所有文本。ClearCedeFocusKeys
- 移除字段中导致焦点转移的所有按键。GetCasing
- 获取控件中字段的字符大小写。默认值为CharacterCasing.Normal
。GetFieldText
- 获取控件中字段的文本。GetLeadingZeros
- 获取一个非空字段是否具有前导零。默认值为false
。GetMaxLength
- 获取字段允许的最大字符数。默认值为3
。GetRangeHigh
- 获取字段允许的最大值。默认值基于字段的最大长度和值格式。GetRangeLow
- 获取字段允许的最小值。默认值为0
。GetSeparatorText
- 获取控件中分隔符的文本。GetValue
- 获取控件中字段的值。如果字段为空,则其值为其低范围值。GetValueFormat
- 获取控件中字段的值格式。默认值为ValueFormat.Decimal
。HasFocus
- 获取控件中字段是否具有输入焦点。IsBlank
- 获取控件中字段是否为空。ResetCedeFocusKeys
- 将字段重置为其默认的焦点转移键,即 [空格键]。SetCasing
- 设置控件中字段的字符大小写。CharacterCasing.Lower
会最小化具有ValueFormat.Hexadecimal
值格式的字段的水平尺寸。SetFieldText
- 设置控件中字段的文本。SetFocus
- 将输入焦点设置为控件中的一个字段。SetLeadingZeros
- 设置一个非空字段是否具有前导零。SetMaxLength
- 设置字段允许的最大字符数。最小值为1
;最大值取决于值格式:十进制值为9
个字符,十六进制值为7
个字符。SetRange
- 设置控件中字段允许的最小值和最大值。SetSeparatorText
- 设置控件中分隔符的文本。SetValue
- 设置控件中字段的值。SetValueFormat
- 设置控件中字段的值格式。ToString
- 获取控件的文本。如果任何字段为空,则该字段的文本将是其低范围值。
该client(客户端)代码可以为公共事件 FieldChangedEvent
注册一个处理程序,以便在控件中任何字段的文本发生更改时收到通知。另一个公共事件 FieldValidatedEvent
会在任何字段的文本得到验证时发出通知。请注意,Text
和 ToString()
可能不会返回相同的值。如果控件中有任何空字段,Text
将返回反映空字段的值。ToString()
会用该字段的低范围值填充任何空字段。
创建 MACAddressControl
这是创建简单的 MACAddressControl
的源代码。
using System;
using System.Windows.Forms;
using FlexFieldControlLib;
namespace TestFlexFieldControl
{
class MACAddressControl : FlexFieldControl
{
public MACAddressControl()
{
// the format of this control is 'FF:FF:FF:FF:FF:FF'
// set FieldCount first
//
FieldCount = 6;
// every field is 2 digits max
//
SetMaxLength( 2 );
// every separator is ':'...
//
SetSeparatorText( ":" );
// except for the first and last separators
//
SetSeparatorText( 0, String.Empty );
SetSeparatorText( FieldCount, String.Empty );
// the value format is hexadecimal
//
SetValueFormat( ValueFormat.Hexadecimal );
// use leading zeros for every field
//
SetLeadingZeros( true );
// use uppercase only
//
SetCasing( CharacterCasing.Upper );
// add ':' key to cede focus for every field
//
KeyEventArgs e = new KeyEventArgs( Keys.OemSemicolon );
AddCedeFocusKey( e );
// this should be the last thing
//
Size = MinimumSize;
}
}
}
构造函数中的第一步应该是始终设置控件的 FieldCount
。否则,任何先前的设置都将被重置。例如,如果每个字段的值格式都设置为 ValueFormat.Hexadecimal
,然后更改了 FieldCount
,则每个字段的值格式都会重置为其默认值 ValueFormat.Decimal
。
下一步是设置每个字段允许的最大字符数。在这种情况下,每个字段都通过 SetMaxLength( 2 )
设置为相同的最大长度。或者,可以单独设置每个字段:SetMaxLength( 0, 2 )
、SetMaxLength( 1, 2 )
、SetMaxLength( 2, 2 )
等。SetMaxLength
中的第一个参数是控件中字段的零基索引。
默认情况下,每个分隔符的文本根据其在控件中的位置,分别为 "<"、"><" 或 ">"。对于此 MACAddressControl
,除了第一个和最后一个分隔符外,每个分隔符的文本都是 ":"。SetSeparatorText( ":" )
将所有分隔符的文本设置为 ":"。为了清除第一个和最后一个分隔符的文本,调用了 SetSeparatorText( 0, String.Empty )
和 SetSeparatorText( FieldCount, String.Empty )
。
每个字段的默认值格式是 ValueFormat.Decimal
,但此控件在每个字段中使用十六进制值。调用 SetValueFormat( ValueFormat.Hexadecimal )
将控件中的所有字段设置为十六进制值格式。或者,可以调用带字段索引的 SetValueFormat
来设置单个字段的值格式。
由于 MAC 地址通常在每个字段中显示前导零(例如,“08:09:0A:0B:0C:0D”,而不是“8:9:A:B:C:D”),因此通过调用 SetLeadingZeros( true )
将每个字段设置为显示前导零。或者,可以调用带字段索引的 SetLeadingZeros
来单独设置每个字段的前导零属性。默认情况下,每个字段不显示前导零。
此控件通过调用 SetCasing( CharacterCasing.Upper )
来强制所有字段中的十六进制字母显示为大写。如果用户在任何字段中输入“a”,控件将在该字段中显示“A”。或者,可以调用带字段索引的 SetCasing
来单独设置每个字段的字符大小写。为了方便用户,此控件将 [;] 键添加为每个字段的焦点转移键,使用
KeyEventArgs e = new KeyEventArgs( Keys.OemSemicolon );
AddCedeFocusKey( e );
如果字段的值可以用一个字符表示,用户可以输入该字符,然后按 [;] 键或 [空格键] 将控件的输入焦点移至下一个字段。或者,可以调用带字段索引的 AddCedeFocusKey
来单独设置每个字段的焦点转移键。
构造函数中的最后一个调用 Size = MinimumSize
会强制控件尽可能小。随着设置的变化,控件只会增长以适应它们;它不会自动收缩。一旦控件放置在窗体上,就可以根据需要调整其大小。
历史
- 2008 年 4 月 29 日
- 添加了
PreviewKeyDown
、KeyDown
和KeyUp
事件的传播。
- 添加了
- 2007 年 11 月 20 日
- 更改
FieldCount
时,添加了在重新创建子控件时调用Dispose()
。感谢 Glenn 报告此问题。
- 更改
- 2007 年 10 月 23 日
ReadOnly
现在应该真正是只读的。
- 2007 年 10 月 4 日
- 为某些鼠标事件添加了正确的事件传播。
- 添加了
AnyBlank
属性。 - 删除了多余的代码。
- 解决了计算文本大小时潜在的资源泄漏问题。
- 符合 FxCop 1.35。
- 2007 年 7 月 23 日
- 修复了与设置带前导零的字段文本相关的错误。再次感谢 zeno_nz 报告此问题。
- 2007 年 7 月 15 日
GotFocus
和LostFocus
事件得到一致引发。- 添加了
AllowInternalTab
属性以允许在控件内进行制表。默认值为false
。
- 2007 年 6 月 27 日
- 对
Text
属性的更改在设计模式下得以保留。 - 库的客户端可以捕获
KeyPress
事件。感谢 zeno_nz 请求此增强功能。
- 对
- 2007 年 6 月 5 日
- 首次发布