带按键验证的 StringBox 控件





5.00/5 (4投票s)
此 StringBox 控件使用正则表达式和一点粘合逻辑实现按键验证
引言
本文介绍了一种使用正则表达式和一些简单逻辑进行按键验证的方法。正则表达式模式用于验证按键输入,而不考虑光标位置。这里提供了6个用于6种不同字符串模式的类。用户可以根据需要创建新模式。一个布尔函数指示StringBox
的文本已完成,可供应用程序使用。
背景
我开发的一些桌面应用程序需要输入IP地址。我需要一种简单的方法,让用户在IP地址框中输入字符,同时只允许他们根据光标位置输入正确的字符。正则表达式是验证最终字符串的绝佳方法,但它们无法在输入时验证部分字符串。此代码中的类和模式解决了这个问题。
Using the Code
演示窗口
下面是一个演示这些类的窗口。六个文本框将只接受与其相应标签指定的正确按键。当StringBox
拥有100%有效且完整的string
时,复选框将变为选中状态。下载可执行文件并试用一下。
此窗口背后的主代码非常简单。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void sbIPv4_TextChanged(object sender, EventArgs e)
{
cbIPv4.Checked = ((StringBox.StringBox)sender).IsComplete();
}
private void sbPort_TextChanged(object sender, EventArgs e)
{
cbPort.Checked = ((StringBox.StringBox)sender).IsComplete();
}
private void sbIPv4Port_TextChanged(object sender, EventArgs e)
{
cbIPv4Port.Checked = ((StringBox.StringBox)sender).IsComplete();
}
private void sbEmailAddress_TextChanged(object sender, EventArgs e)
{
cbEmailAddress.Checked = ((StringBox.StringBox)sender).IsComplete();
}
private void sbIPv6_TextChanged(object sender, EventArgs e)
{
cbIPv6.Checked = ((StringBox.StringBox)sender).IsComplete();
}
private void sbNANPPhoneNumber_TextChanged(object sender, EventArgs e)
{
cbNANPPhoneNumber.Checked = ((StringBox.StringBox)sender).IsComplete();
}
}
正如您所见,当各自的StringBox TextChanged
事件触发时,复选框就会被设置。
StringBox 类
验证按键以匹配特定模式是一个分两步的过程。第一步是检查是否只允许根据光标位置接受合适的字符。例如,IP地址由四个以点分隔的十进制字节组成。每个部分都在0-255之间。可以轻松创建正则表达式模式来实现这一点。IP地址的正则表达式模式可能如下所示:
[\d]{1,3}[.][\d]{1,3}[.][\d]{1,3}[.][\d]{1,3}
这只会在我们有一个完整的表达式进行检查时匹配。因此,在输入时检查文本将不起作用。为了解决这个问题,我们修改模式,使其匹配完整IP地址的所有可能的较短版本。我们可以使用此模式:
[\d]{0,3}[.]?[\d]{0,3}[.]?[\d]{0,3}[.]?[\d]{0,3}
请注意,使用此模式,无论字符串输入了多少,我们都会获得匹配,但只允许数字和点出现在正确的位置。
现在让我们看看在基类StringBox
中使用此模式的按键代码:
private void StringBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.Handled) return;
// insert key into temp string
var temp = SelectionLength > 0
? Text.Substring(0, SelectionStart) + e.KeyChar +
Text.Substring(SelectionStart + SelectionLength)
: Text.Insert(SelectionStart, e.KeyChar.ToString());
// if doesn't match pattern or length then reject the key by setting handled = true
var handled = !(regex.IsMatch(temp) && (regex.Match(temp).Length == temp.Length));
// do an additional check to make sure individual parts are correct
if (!handled)
handled = !IsValid(temp);
e.Handled = handled;
}
此代码创建了一个temp
string
,它是Text
string
加上插入到正确位置的按键。然后,它将此temp
string
与正则表达式模式进行匹配检查,并检查匹配长度是否与temp
长度相同。如果任一条件不满足,则通过设置handled = true
来拒绝按键。
到目前为止,一个IP地址999.999.999.999
将被接受。这就是第二步的作用。keypress
事件还必须使用虚拟函数IsValid
验证temp
字符串。如果此检查失败,则keystroke
也会被拒绝。每个派生类都应重写此虚拟函数。
StringIPv4 类
查看下面的StringIPv4类代码:
public class StringIPv4 : StringBox
{
public StringIPv4()
{
Pattern = @"[\d]{0,3}[.]?[\d]{0,3}[.]?[\d]{0,3}[.]?[\d]{0,3}";
}
/// <summary>
/// Check if entire string is valid IPv4 string
/// </summary>
/// <returns>true if valid IPv4 string</returns>
public override bool IsComplete()
{
// make sure there are 4 parts
var s = Text.Split(new[] {'.'}, StringSplitOptions.RemoveEmptyEntries);
return s.Length == 4;
// do not need to do range check since 'IsValid' already does this
// alternate IPv4 check method
//if (!IPAddress.TryParse(Text, out var address)) return false;
//if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
// return true;
//return false;
}
/// <summary>
/// Checks if 'str' matches IPv4 complete pattern
/// Called once each keystroke
/// </summary>
/// <param name="str">temp string to check</param>
/// <returns>true if string is valid</returns>
protected override bool IsValid(string str)
{
// make sure each part is range limited
var s = str.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var t in s)
{
var x = Convert.ToInt32(t);
if (x < 0 || x > 255) return false;
}
return true;
}
}
首先,我们看到这个类是从StringBox
类派生的,并在构造函数中定义了一个正则表达式模式。
IsValid
函数重写了基类的虚拟函数。该函数将temp
字符串按点分隔成离散的部分,并检查每个部分是否在0-255的范围内。如果值不在该范围内,则返回false
,这将拒绝按键。
应用程序通常会调用IsComplete
函数来检查Text
字符串是否已完成并可供使用。在这种情况下,我们只需要检查字符串中是否有4个字节。IsValid
已经检查了每个部分是否在范围内。另一种方法是将Text
解析为InterNetwork
类型的IP地址。然后,完整的string
就是一个完全有效的IPv4地址。
所提供的六个特定类涵盖了常见的应用程序string
类型。目标是使用正则表达式进行按键检查,并使用简单的、高级别的检查来验证string
。这些类将出现在您的Visual Studio工具箱窗口中,以便拖放到您的窗口上。
注释
创建新的StringBox
类:
- 将新
StringBox
从基类派生出来。 - 创建合适的模式作为第一步。该模式必须匹配最终
string
的所有可能子字符串。 - 创建
IsComplete
函数,作为对Text
string
的最终测试。 - 创建
IsValid
函数,作为按键检查第二步的一部分。
关注点
创建这段代码让我看到了使用非传统正则表达式的新方法。基本上是如何使用一个似乎匹配string
及其所有子string
的模式。或者正则表达式如何用于比仅完全string
验证更多的用途。
致谢
这是在textbox
中进行按键验证的众多方法中的一种。我没有直接链接到特定来源,但在这里CodeProject上快速搜索一下就会发现很多。
我能引用的唯一链接是一个远房亲戚,NumberBox,我之前发布过。它对SNFS数字格式进行按键验证。
历史
- 2020年7月22日:初始版本