CSLA.Net学习(3)INotifyPropertyChanged和IDataErrorInfo
今天晕晕糊糊的看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
作者:太一吾鱼水
文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。
欢迎大家留言交流,转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2013-03-06 [地图代数]ArcGIS栅格计算器的应用
2012-03-06 BindingSource组件使用