这也是前两天在课堂上的一个案例,我们实现了自定义的文本框验证器。这是一个实现了IExtenderProvider 的组件。该范例部分代码改编自MSDN
这个验证组件,可以为窗体上任意多个文本框提供验证,大致有如下几种方式
1. 必填项检查
2.范围检查(例如最小值为5,最大值为100)
3. 类型检查
4. 正则表达式检查
大致的用法是:
1. 将该组件拖拽到窗体上,同时还要拖拽一个ErrorProvider
2. 设置该组件的一个属性,将其与ErrorProvider绑定
3. 设置哪些文本框需要进行什么样的验证
4. 在窗体代码中,例如提交按钮代码中,使用下面的方式来做验证
//使用自定义验证器
if (!textBoxValidator1.IsValid(out errorMessage))
MessageBox.Show(String.Format("当前数据没有通过:{0}", errorMessage));
else
{
employeesBindingSource.EndEdit();
tableAdapterManager.UpdateAll(employeesDataSet);
this.Text = firstNameTextBox.Text + "," + lastNameTextBox.Text;
SetControlStatus(false);
}
5. 运行效果大致如下
该组件的完整代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections;
using System.Text.RegularExpressions;
namespace NorthwindApplication
{
///
/// 这个类型是专门用来做文本框验证的
/// 作者:陈希章
///
///
[ProvideProperty("DataType", typeof(Control))]
[ProvideProperty("DisplayName", typeof(Control))]
[ProvideProperty("MinValue", typeof(Control))]
[ProvideProperty("MaxValue", typeof(Control))]
[ProvideProperty("Required", typeof(Control))]
[ProvideProperty("RegularExpression", typeof(Control))]
//这是定义的几个属性
public class TextBoxValidator : Component, IExtenderProvider
{
[Description("设置一个关联的ErrorProvider")]
public ErrorProvider ErrorProvider { get; set; }
#region IExtenderProvider 成员
public bool CanExtend(object extendee)
{
return extendee.GetType() == typeof(TextBox);
}
#endregion
///用一个hashTable来保存控件的设置
Hashtable tb = new Hashtable();
private TextBoxValidatorProvidedProperties GetAddControl(Control ctrl)
{
if (!tb.ContainsKey(ctrl))
{
TextBoxValidatorProvidedProperties prop = new TextBoxValidatorProvidedProperties();
tb.Add(ctrl, prop);
ctrl.Validated += new EventHandler(ctrl_Validated);
}
return tb[ctrl] as TextBoxValidatorProvidedProperties;
}
void ctrl_Validated(object sender, EventArgs e)
{
ProcessError((Control)sender);
}
private void ProcessError(Control ctrl)
{
TextBoxValidatorProvidedProperties prop = (TextBoxValidatorProvidedProperties)tb[ctrl];
string message = GetErrorMessage(ctrl);
if (!string.IsNullOrEmpty(message) && ErrorProvider != null)
ErrorProvider.SetError(ctrl, message);
else
ErrorProvider.SetError(ctrl, "");
}
private string GetErrorMessage(Control ctrl)
{
Type[] types = new[]{
typeof(string),
typeof(byte),
typeof(Int16),
typeof(Int32),
typeof(Int64),
typeof(Single),
typeof(double),
typeof(decimal),
typeof(DateTime)
};
TextBoxValidatorProvidedProperties props = (TextBoxValidatorProvidedProperties)tb[ctrl];
string displayName;
if (string.IsNullOrEmpty(props.DisplayName))
displayName = ctrl.Name;
else
displayName = props.DisplayName;
string value = ctrl.Text;//检查是不是必填项
if (value.Length == 0)
{
if (props.Required)
return displayName + " 是必填的!";
else
return string.Empty;
}
Type dataType = types[(int)props.DataType];
try
{
object o = Convert.ChangeType(value, dataType);//尝试强制转换到某个类型
switch (props.DataType)
{
case DataTypeConstants.ByteType:
case DataTypeConstants.Int16Type:
case DataTypeConstants.Int32Type:
case DataTypeConstants.Int64Type:
if (Convert.ToDecimal(value) != Convert.ToInt64(value))
return "在文本框" + displayName + "中不允许有小数点";
break;
default:
break;
}
}
catch (Exception)
{
return string.Format("文本框{0}中的值{1}无法转换为{2}类型",
displayName,
value,
dataType);
}
//验证正则表达式
if (props.RegularExpression.Length > 0)
{
if (!Regex.IsMatch(value, props.RegularExpression))
{
return string.Format("文本框{0}中的值{1}不满足正则表达式{2}的验证规则",
displayName,
value,
props.RegularExpression);
}
}
if (props.MinValue.Length > 0)
{
if (Convert.ChangeType(value, dataType).GetHashCode() <
Convert.ChangeType(props.MinValue, dataType).GetHashCode())
return string.Format("文本框{0}中的值{1}太小了,应该至少是{2}",
displayName,
value,
props.MinValue);
}
if (props.MaxValue.Length > 0)
{
if (Convert.ChangeType(value, dataType).GetHashCode() >
Convert.ChangeType(props.MaxValue, dataType).GetHashCode())
return string.Format("文本框{0}中的值{1}太大了,应该最大是{2}",
displayName,
value,
props.MaxValue);
}
return string.Empty;
}
#region 属性
///定义一系列的Get和Set方法来完成属性
///
public DataTypeConstants GetDataType(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).DataType;
else
return DataTypeConstants.StringType;
}
public void SetDataType(Control ctrl, DataTypeConstants dataType)
{
GetAddControl(ctrl).DataType = dataType;
}
public string GetMinValue(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).MinValue;
else
return string.Empty;
}
public void SetMinValue(Control ctrl, string value)
{
if (value == null) value = string.Empty;
GetAddControl(ctrl).MinValue = value;
}
public string GetMaxValue(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).MaxValue;
else
return string.Empty;
}
public void SetMaxValue(Control ctrl, string value)
{
if (value == null) value = string.Empty;
GetAddControl(ctrl).MaxValue = value;
}
public string GetDisplayName(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).DisplayName;
else
return string.Empty;
}
public void SetDisplayName(Control ctrl, string value)
{
GetAddControl(ctrl).DisplayName = value;
}
public string GetRegularExpression(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).RegularExpression;
else
return string.Empty;
}
public void SetRegularExpression(Control ctrl, string value)
{
GetAddControl(ctrl).RegularExpression = value;
}
public bool GetRequired(Control ctrl)
{
if (tb.ContainsKey(ctrl))
return ((TextBoxValidatorProvidedProperties)tb[ctrl]).Required;
else
return false;
}
public void SetRequired(Control ctrl, bool value)
{
GetAddControl(ctrl).Required = value;
}
#endregion
#region 验证逻辑
public bool IsValid(out string summary)
{
summary = this.ValidationSummary;
return summary.Length == 0;
}
private string ValidationSummary
{
get
{
var messages = this.InvalidMessages;
StringBuilder sb = new StringBuilder();
foreach (var item in messages)
{
sb.AppendFormat("{0}/n", item.ToString());
}
return sb.ToString();
}
}
private ArrayList InvalidMessages
{
get
{
SortedList olInvalidMessages = new SortedList();
string message;
foreach (Control ctrl in tb.Keys)
{
message = GetErrorMessage(ctrl);
if (!string.IsNullOrEmpty(message))
olInvalidMessages.Add(ctrl.TabIndex, message);
}
ArrayList colErrorsByIndex = new ArrayList();
foreach (var item in olInvalidMessages.Values)
{
colErrorsByIndex.Add(item.ToString());
}
return colErrorsByIndex;
}
}
#endregion
}
public class TextBoxValidatorProvidedProperties
{
public DataTypeConstants DataType;
public string MinValue;
public string MaxValue;
public string DisplayName = string.Empty;
public bool Required = false;
public string RegularExpression = string.Empty;
}
///
/// 定义一个枚举,用来让用户可以选择数据类型
///
public enum DataTypeConstants
{
StringType,
ByteType,
Int16Type,
Int32Type,
Int64Type,
SingleType,
DoubleType,
DecimalType,
DateTimeType
}
}