容器扩展属性 IExtenderProvider 实现WinForm通用数据验证组件
大家对如下的Tip组件使用应该不陌生,要想让窗体上的控件使用ToolTip功能,只需要拖动一个ToolTip组件到窗口,所有的控件就可以使用该功能,做信息提示。
本博文要记录的,就是通过容器扩展属性 IExtenderProvider,来实现一个数据验证组件,通过将组件拖动到窗口后,使得上面的所有控件可以实现数据验证!
设置下面两个扩展属性,即可使用组件
调用开放的验证方法public bool VerifyData(Control ct = null)后,验证样式为:
1.实现思路:
通过记录每个控件的验证规则,和相应验证提示信息,结合ErrorProvider组件,为控件实现提示信息。时间不多,直接上代码吧,看注释。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CFW.WinFormBase.Controls { /// <summary> /// 为控件提供数据验证规则扩展属性 /// </summary> [Description("为菜单项或控件提供描述扩展属性")] [ProvideProperty("Verify", typeof(Control))] [ProvideProperty("VerifyMsg", typeof(Control))] public class ControlVerify : Component, IExtenderProvider { /// <summary> /// 存储所服务的控件及其验证规则 /// </summary> readonly Dictionary<Control, Validata> dic; /// <summary> /// 存储所服务的控件及其验证提示信息 /// </summary> readonly Dictionary<Control, string> msgDic; /// <summary> /// 错误验证提示类 /// </summary> public ErrorProvider errTip; /// <summary> /// 创建一个Verify类 /// </summary> public ControlVerify() { dic = new Dictionary<Control, Validata>(); msgDic = new Dictionary<Control, string>(); errTip = new ErrorProvider(); } /// <summary> /// 数据验证 /// </summary> /// <returns></returns> /// <param name="ct">验证控件所在容器 null为全部</param> public bool VerifyData(Control ct = null) { //errTip.Clear(); var ret = true; foreach (var item in dic) { var data = item.Key.Text;//数据 var verify = item.Value;//验证规则 if (ct != null && item.Key.Parent != ct) { errTip.SetError(item.Key, ""); continue; } if (DataVali(data,verify)) { errTip.SetError(item.Key, ""); } else { string errMsg = msgDic[item.Key]; errTip.SetError(item.Key, errMsg.Length > 0 ? errMsg : "请输入正确的数据"); ret = false; } } return ret; } /// <summary> /// 清除验证提示 /// </summary> public void ClearVerify() { errTip.Clear(); } private bool DataVali(string data,Validata vali) { bool ret = false; var _data = data.Trim(); switch (vali) { case Validata.无: ret = true; break; case Validata.Require: if (_data.Length > 0) ret = true; break; case Validata.AgeValue: if (!_data.IsNullOrEmpty() && !_data.IsMatch("^[0 - 9] + $")) { ret = false; } else { ret = true; } break; case Validata.DateValue: ret = _data.IsMatch(@"^(\d{2}|\d{4})((0[1-9])|(1[0-2]))((0[1-9])|((1|2)[0-9])|30|31)$"); break; case Validata.NumberValue: ret = _data.IsMatch(@"^[0 - 9] + $"); break; case Validata.TelValue: ret = _data.IsPhone(); break; case Validata.IntValue: int parse = 0; ret = int.TryParse(_data,out parse); break; case Validata.IdCardValue: ret = _data.IsIdCard(); break; default: break; } return ret; } /// <summary> /// 获取菜单项描述 /// </summary> [Description("设置验证规则")] //虽然方法为Get,但在VS中显示为“设置”才符合理解 [DefaultValue(Validata.无)] public Validata GetVerify(Control item) { //从集合中取出该item的描述 Validata value; string str; dic.TryGetValue(item, out value); msgDic.TryGetValue(item, out str); return value; } /// <summary> /// 设置验证规则描述 /// </summary> public void SetVerify(Control item, Validata value) { if (item == null) { return; } if (value == Validata.无) { //从集合中移除该item,并取消其相关事件绑定 dic.Remove(item); msgDic.Remove(item); } else { //添加或更改该item的描述 dic[item] = value;//这种写法对于dic中不存在的Key,会自动添加 msgDic[item] = ""; } } /// <summary> /// 获取菜单项描述 /// </summary> [Description("设置验证提示")] //虽然方法为Get,但在VS中显示为“设置”才符合理解 [DefaultValue("")] public string GetVerifyMsg(Control item) { //从集合中取出该item的描述 string value; msgDic.TryGetValue(item, out value); return value; } /// <summary> /// 设置验证规则提示信息 /// </summary> public void SetVerifyMsg(Control item, string value) { if (item == null) { return; } if (value == "") { //从集合中移除该item,并取消其相关事件绑定 msgDic.Remove(item); } else { //添加或更改该item的描述 msgDic[item] = value;//这种写法对于dic中不存在的Key,会自动添加 } } /// <summary> /// 是否可为某对象扩展属性 /// </summary> public bool CanExtend(object extendee) { return true; } } public enum Validata { 无, Require, AgeValue, DateValue, NumberValue, TelValue, IntValue, IdCardValue, } }
2.调用方法:
Verify.VerifyData();
在时间轴上留下点什么,作为个程序员,就在cnblog上吧,我不是技术大牛,也不是IT狂热者,说不上是我选了它还是它选了我,结果是现在我是一名程序员,我对它很感兴趣,不为以后做业务大佬、行业顶尖,只想在自己能力范围内,把事情做到最好,在博客园记录下自己的历程吧,工作,学习,感情,生活。