验证的基本流程和基本场景
- 验证一个控件,其步骤如下
- 获取控件的值
- 提供默认的控件的取值方法
- 可以通过注册控件的方法来注册获取某个控件的值
- 判别要验证的类型:
isNumber
,NotNull
……- 通过绑定到的实体类的特性,我们可以知道具体的类型
- 在调用方法中指定验证的类型
- 调用验证函数进行验证
- 默认的调用函数
- 通过方法传递进来的验证函数
- 验证失败提示失败信息
- 基本的类型有默认的提示:不能为空、必须为数字、必须为日期……
- 通过方法传入
- 提示的方法可以由子类进行重写,这样就能根据不同的子类方法,达到实现不同的提示类型
- 获取控件的值
- 验证多个控件,其实就是递归所有的控件组,调用“一个控件的验证”
- 一个
Form
下的所有控件 - 某个容器控件(比如
Panel
、TabPage
……)下的所有控件
- 一个
使用方法示例
以下通过一些具体的示例来展示上述验证类的使用方法
支持DotNetBar的控件以及使用DotNetBar的气泡控件和高亮控件进行提示
构造函数
private BalloonValidator(Type type)
: base(type)
{
Register<TextBoxX>(new[] { "txt" }, t => ((TextBoxX)t).Text)
.Register<ComboBoxEx>(new[] { "ddl" }, t =>
{
var ddl = (ComboBoxEx)t;
if (ddl.DropDownStyle == ComboBoxStyle.DropDown)
{
return ddl.Text;
}
return ddl.SelectedIndex > 0 ? "MSG" : string.Empty;
})
.Register<CheckBoxX>(new[] { "chk" }, t => ((CheckBoxX)t).CheckState == CheckState.Indeterminate ? string.Empty : "MSG")
.Register<IntegerInput>(new[] { "ii" }, t => ((IntegerInput)t).Text);
}
public BalloonValidator(Type type, BalloonTip tip)
: this(type)
{
_tip = tip;
}
public BalloonValidator(Type type, BalloonTip tip, Highlighter highlighter)
: this(type, tip)
{
_highligther = highlighter;
}
重写错误验证时的提示
public override Validator HandleError(Control ctrl, string errorMsg)
{
ShowBalloonTip(ctrl, errorMsg);
if (_highligther != null) _highligther.SetHighlightColor(ctrl, eHighlightColor.Red);
return this;
}
重新验证正确时的方法
public override Validator HandleSuccess(Control ctrl)
{
_tip.Remove(ctrl);
if (_highligther != null) _highligther.SetHighlightColor(ctrl, eHighlightColor.None);
return this;
}
验证使用步骤
在Model中设置特性
[DataType(DataType.Currency, ErrorMessage = "“运费”必须为数字")]
public double StartYunShu
{
get;
set;
}
目前支持的特性为:
DataType
:数据类型DataType.Currency
:数值类型DataType.Date
、DataType.DateTime
:日期类型
Required
:不能为空StringLength
:StringLength.Max
:字符长度最长不能超过多少RegularExpression
:符合某个正则表达式
注意控件名称的命名规则要有一定的规范
控件命名规则为:[控件前缀] + [Model的属性名称]
目前系统的前缀规范为:
- 文本框TextBox:txt
- 下拉框ComboBox:ddl
- 日期控件:DateTimePicker:dtp
- 复选框:CheckBox:chk
- 数字输入控件:IntegerInput:ii
在CheckInput方法中进行验证
if (!_validator.Verify(Controls)) return false;
实际使用示例
-
实例化一个验证类:
_validator = new BalloonValidator(typeof(NTier.Entity.CWGL_AccountHis), balloonTip1, highlighter1);
-
对所有默认的控件进行验证:
if (!_validator.Verify(Controls)) return false;
-
对控件名称和实体属性名称无法匹配的进行手动验证:
if (!_validator.Verify(txtMoney, "发生金额", Validator.VerifyType.Number)) return false;
——实体类NTier.Entity.CWGL_AccountHis
没有类型Money这样的属性 -
对于由多个控件组成的属性,是无法根据属性的类型进行验证的,这个时候需要手动写验证函数:
if (!_validator.Verify(lblUnSureCost, "请选择费用是否确定", () => rbtnYes.Checked || rbtnNo.Checked)) return false;
-
对于复杂的验证方法,同样可以通过自定义验证函数进行验证:
if (!((NTier.Entity.CWGL_AccountNew)ddlFNumber1.SelectedItem).FisDetail) { if (!_validator.Verify(ddlFNumber2, "二级科目", Validator.VerifyType.Required)) return false; if (ddlFNumber2.SelectedIndex > 0 && !((NTier.Entity.CWGL_AccountNew)ddlFNumber2.SelectedItem).FisDetail) { if (!_validator.Verify(ddlFNumber3, "三级科目", Validator.VerifyType.Required)) return false; } }
实现的类的基本方法概览
注册控件
///首先定义控件存储对象
class CtrlObject
{
public string Key { get; private set; }
public Type Type { get; private set; }
public string[] Prefix { get; private set; }
public Func<Component, object> GetValue { get; private set; }
public CtrlObject(Type type, string[] prefix, Func<Component, object> getValueHandler)
{
if (getValueHandler == null) throw new ArgumentNullException("getValueHandler");
Type = type;
Prefix = prefix;
GetValue = getValueHandler;
Key = type.FullName;
}
}
public Validator Register<TCtrl>(string[] prefix, Func<Component, object> getValue, bool cover = false)
{
var ctrlObj = new CtrlObject(typeof(TCtrl), prefix, getValue);
if (!_getValueHandler.ContainsKey(ctrlObj.Key)) _getValueHandler.Add(ctrlObj.Key, ctrlObj);
else if (cover) _getValueHandler[ctrlObj.Key] = ctrlObj;
return this;
}
在构造函数中注册默认的控件
private Validator()
{
Register<TextBox>(new[] { "txt" }, t => ((TextBox)t).Text)
.Register<ComboBox>(new[] { "ddl" }, t => ((ComboBox)t).SelectedIndex > 0 ? "MSG" : string.Empty)
.Register<DateTimePicker>(new[] { "dtp" }, t =>
{
var date = (DateTimePicker)t;
if (date.Checked) return date.Value;
return null;
});
}
public Validator(Type t)
: this()
{
if (t != null)
{
foreach (var p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (!_properties.ContainsKey(p.Name)) _properties.Add(p.Name, p);
}
}
}
验证控件
验证单一控件是否合法
public bool Verify(Control ctrl)
{
var args = OnBeforeVerify(ctrl);
return args.Canceled || ValidateInner(ctrl);
}
private bool ValidateInner(Control ctrl, bool triggerAllInvalidControl = true)
{
if (_properties.Count == 0) throw new Exception("请先设置要验证的对象类型!");
//获取对应的处理器,如果没有,则默认不加入验证
var handler = GetHandler(ctrl);
if (handler == null) return true;
var value = handler.GetValue(ctrl);
var property = GetProperty(handler.Prefix, ctrl);
if (property == null) return true;//找不到对应的属性
var result = ((ValidateRequired(property, value)
?? ValidateDataType(property, value))
?? ValidateStingLength(property, value))
?? ValidateRegularExpression(property, value);
if (result != null)
{
if (triggerAllInvalidControl)
{
foreach (var key in _invalidControls.Keys)
{
if (ctrl.Name.Equals(key)) continue;
ValidateInner(_invalidControls[key], false);
}
}
HandleError(ctrl, result.ErrorMessage);
if (triggerAllInvalidControl && !_invalidControls.ContainsKey(ctrl.Name))
_invalidControls.Add(ctrl.Name, ctrl);//添加到错误列表
}
else
{
HandleSuccess(ctrl);
if (triggerAllInvalidControl && _invalidControls.ContainsKey(ctrl.Name))
_invalidControls.Remove(ctrl.Name);//从错误列表中删除已经验证成功的控件
}
return result == null;
}
验证某个容器下所有的控件是否合法
/// <summary>
/// 验证某个控件下的所有子控件
/// </summary>
/// <param name="ctrls">The CTRLS.</param>
/// <returns></returns>
public bool Verify(Control.ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (Ignore(ctrl)) continue;
if (IsContainer(ctrl))
{
if (!Verify(ctrl.Controls)) return false;
}
else
{
if (!Verify(ctrl)) return false;
}
}
return true;
}
验证是否为某个类型
public bool Verify(Control ctrl, string name, VerifyType type)
{
var handler = GetHandler(ctrl);
if (handler == null) throw new Exception(string.Format("找不到类型“{0}”的获取值的处理器!", ctrl.GetType()));
var value = handler.GetValue(ctrl);
if (value == null || string.IsNullOrEmpty(value.ToString()))
{
if (type.HasFlag(VerifyType.Required))
{
HandleError(ctrl, string.Format("{0}不能为空!", name));
return false;
}
}
else
{
if (type.HasFlag(VerifyType.Number))
{
if (!ConvtUtil.GetNullable<double>(value).HasValue)
{
HandleError(ctrl, string.Format("{0}必须为数字!", name));
return false;
}
}
}
return true;
}
在调用验证方法时传入指定的验证函数
public bool Verify(Control ctrl, string msg, Func<bool> verifyFunc)
{
var args = OnBeforeVerify(ctrl);
if (args.Canceled) return true;
if (!verifyFunc())
{
HandleError(ctrl, msg);
return false;
}
HandleSuccess(ctrl);
return true;
}
验证成功时或者失败时的处理
public virtual Validator HandleError(Control ctrl, string errorMsg)
{
ctrl.Focus();
MessageBoxHelper.ShowWarning(errorMsg);
return this;
}
public virtual Validator HandleSuccess(Control ctrl) { return this; }