今天晕晕糊糊的看CSLA.net,希望能找到验证数据正确性的方法,还是摸索出了INotifyPropertyChanged, IDataErrorInfo接口的使用方法,通过INotifyPropertyChanged实现了响应属性改变的事件,通过 IDataErrorInfo接口实现了在DataGridView或者GridControl中显示验证信息。
先看一个数据实体的抽象类:
1 public abstract class BaseModel : INotifyPropertyChanged, INotifyPropertyChanging, IDataErrorInfo 2 { 3 protected BusinessRules mBusinessRules = new BusinessRules(); 4
5 public event PropertyChangedEventHandler PropertyChanged; 6
7 public event PropertyChangingEventHandler PropertyChanging; 8
9 public BaseModel() 10 { 11 mBusinessRules.info = this; 12 AddRule(); 13 } 14
15 public virtual void AddRule() 16 { 17
18 } 19
20 protected virtual void PropertyHasChanged(string name) 21 { 22 var propertyNames = mBusinessRules.CheckRules(name); 23
24 foreach (var item in propertyNames) 25 OnPropertyChanged(item); 26 } 27
28 protected virtual void OnPropertyChanged(string propertyName) 29 { 30 if (PropertyChanged != null) 31 PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); 32
33 } 34
35 protected virtual void OnPropertyChanging(string propertyName) 36 { 37 if (PropertyChanging != null) 38 PropertyChanging.Invoke(this, new PropertyChangingEventArgs(propertyName)); 39
40 } 41
42 #region IDataErrorInfo
43
44 string IDataErrorInfo.Error 45 { 46 get
47 { 48 return "Hello"; 49 } 50 } 51
52 string IDataErrorInfo.this[string columnName] 53 { 54 get { return mBusinessRules.GetBrokenRules(columnName); } 55 } 56
57 #endregion
58
59 }
其中的BusinessRules对象mBusinessRules主要负责验证属性的正确性,这里只实现了一个粗糙版本的,没有抽象出验证规则Rule类。
将属性名和验证规则增加到mBusinessRules对象中,通过IDataErrorInfo的IDataErrorInfo.Error属性和IDataErrorInfo.this[string columnName]索引器验证每一列的正确性。Error是行头显示的提示信息。这里用到了lamda表达式和属性的遍历。
1 public class BusinessRules 2 { 3 List<string> names = new List<string>(); 4 List<string> exp = new List<string>(); 5 public object info;//指向对象本身
6
7 public List<string> CheckRules(string name) 8 { 9 return names; 10 } 11
12 public string GetBrokenRules(string columnName) 13 { 14 for (int i = 0; i < names.Count; i++) 15 { 16 List<object> list = new List<object>(); 17 if (info == null) return null; 18 Type t = info.GetType(); 19 IEnumerable<System.Reflection.PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == columnName.ToLower() select pi; 20 //IEnumerable<System.Reflection.PropertyInfo> property = t.GetProperties();
21 foreach (PropertyInfo prpInfo in property) 22 { 23 string sProName = prpInfo.Name; 24 object obj = prpInfo.GetValue(info, null); 25 if (!Regex.IsMatch(obj.ToString(), exp[i])) 26 { 27 return "Error"; 28 } 29 } 30 } 31 return ""; 32 } 33
34 public void AddRule(string ColName, string RegexExpress) 35 { 36 names.Add(ColName); 37 exp.Add(RegexExpress); 38 } 39 }
接下来是数据实体Student,继承自BaseModel
1 public class Student : BaseModel 2 { 3 public Student(string name) 4 { 5 mName = name; 6 } 7 private string mName; 8 public string Name 9 { 10 get
11 { 12 return mName; 13 } 14 set
15 { 16 if (mName != value) 17 { 18 mName = value; 19 PropertyHasChanged("Name"); 20 } 21 } 22 } 23 public override void AddRule() 24 { 25 mBusinessRules.AddRule("Name", @"^-?\d+$"); 26 } 27
28 }
最后是调用和效果:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 BindingList<Student> list = new BindingList<Student>(); 4 Student a = new Student("张三"); 5 list.Add(a); 6 Student b = new Student("张三三"); 7 list.Add(b); 8 gridControl1.DataSource = list; 9 }
图1 初始化程序 图2修改第一行数据后,第一行错误提示消失
行头没有处理,所以一直有提示信息。
提供一个较完整的验证基类:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Reflection; 5 using System.Text.RegularExpressions; 6
7 namespace AppSurveryTools.Base 8 { 9 public abstract class EntityBase : IDataErrorInfo 10 { 11 protected BussinessRules mBussiness = null; 12
13 public EntityBase() 14 { 15 mBussiness = new BussinessRules(this); 16 AddRules(); 17 } 18 public virtual void AddRules() 19 { 20 } 21 public string Error 22 { 23 get { return ""; } 24 } 25
26 public string this[string columnName] 27 { 28 get
29 { 30 string error = mBussiness.CheckRule(columnName); 31 return error; 32 } 33 } 34 } 35 public class BussinessRules 36 { 37 Dictionary<string, Rule> rules = new Dictionary<string, Rule>(); 38 Object mObj = null; 39 private readonly Type _type; 40 public BussinessRules(object obj) 41 { 42 mObj = obj; 43 _type = mObj.GetType(); 44 } 45 public void AddRules(string property, Rule rule) 46 { 47 if (!rules.ContainsKey(property)) 48 { 49 rules.Add(property, rule); 50 } 51 } 52 public string CheckRule(string columnName) 53 { 54 if (rules.ContainsKey(columnName)) 55 { 56 Rule rule = rules[columnName]; 57 PropertyInfo[] properties = _type.GetProperties(BindingFlags.Public | BindingFlags.Instance); 58 foreach (PropertyInfo prpInfo in properties) 59 { 60 if (prpInfo.Name == columnName) 61 { 62 object obj = prpInfo.GetValue(mObj, null); 63 if (obj==null) 64 { 65 return ""; 66 } 67 if (rule.RuleType == RuleTypes.RegexExpression) 68 { 69 if (!Regex.IsMatch(obj.ToString(), rule.RegexExpression)) 70 { 71 return rule.ErrorText; 72 } 73 } 74 else if (rule.RuleType == RuleTypes.StringRequire) 75 { 76 if (string.IsNullOrEmpty(obj.ToString())) 77 { 78 return rule.ErrorText; 79 } 80 } 81
82
83 } 84 } 85 } 86 return ""; 87 } 88 public void RemoveRule(string property) 89 { 90 if (rules.ContainsKey(property)) 91 { 92 rules.Remove(property); 93 } 94 } 95 } 96 public enum RuleTypes 97 { 98 RegexExpression = 0, 99 Int32Require = 1, 100 DoubleRequire = 2, 101 DataRequire = 3, 102 StringRequire = 4
103 } 104 public class Rule 105 { 106 public RuleTypes RuleType { get; set; } 107 public string ErrorText { get; set; } 108 public string RegexExpression { get; set; } 109 /// <summary>
110 /// 验证规则 111 /// </summary>
112 /// <param name="typeRule">验证类型</param>
113 /// <param name="error">提示信息</param>
114 /// <param name="expression">表达式</param>
115 public Rule(RuleTypes typeRule, string error, string expression) 116 { 117 if (typeRule == RuleTypes.RegexExpression) 118 { 119 if (!string.IsNullOrEmpty(expression)) 120 { 121 RegexExpression = expression; 122 } 123 } 124 RuleType = typeRule; 125 ErrorText = error; 126 } 127
128 public string CheckRule(string RegexExpression) 129 { 130 return ""; 131 } 132 } 133 }
调用方法:
继承基类EntityBase,重载方法AddRules()
1 public override void AddRules() 2 { 3 string express = "^([-]?(\\d|[1-8]\\d)[°](\\d|[0-5]\\d)['](\\d|[0-5]\\d)(\\.\\d+)?[\"]?[NS]?$)"; 4 mBussiness.AddRules("WGS84B", new Rule(RuleTypes.RegexExpression, "请输入正确的纬度数据", express)); 5 string express2 = "^([-]?(\\d|[1-9]\\d|1[0-7]\\d)[°](\\d|[0-5]\\d)['](\\d|[0-5]\\d)(\\.\\d+)?[\"]?[EW]?$)"; 6 mBussiness.AddRules("WGS84L", new Rule(RuleTypes.RegexExpression, "请输入正确的经度数据", express2)); 7 base.AddRules(); 8 }
补充:类似的介绍 http://blog.csdn.net/t673afa/article/details/6066278