ICollectionView有一个Filter属性,接受一个Predicate<object>的委托 来生成过滤视图
准备一个实体数据类
1 /// <summary> 2 /// 测试数据类 3 /// </summary> 4 public class UserDataProxy : DynamicObject 5 { 6 private Dictionary<string, object> _dict = new Dictionary<string, object>(); 7 8 public string Color { get; set; } 9 10 public Guid Guid { get; set; } 11 12 public string Layer { get; set; } 13 14 public string Length { get; set; } 15 16 public string Name { get; set; } 17 18 public string Type { get; set; } 19 20 /// <summary> 21 /// 添加动态属性 22 /// </summary> 23 /// <param name="propertyName"></param> 24 /// <param name="value"></param> 25 public void AddDynamicProperty(string propertyName, object value) 26 { 27 _dict[propertyName] = value; 28 } 29 30 public IEnumerable<string> GetAllProPertyNames() 31 { 32 var list = new List<string>() 33 { 34 "Guid","Type","Layer","Name","Color" 35 }; 36 list.AddRange(GetDynamicMemberNames()); 37 return list; 38 } 39 40 /// <summary> 41 /// 重写获取动态属性的方法 42 /// </summary> 43 /// <returns></returns> 44 public override IEnumerable<string> GetDynamicMemberNames() 45 { 46 return _dict.Keys; 47 } 48 49 /// <summary> 50 /// 获取动态属性的方法 51 /// </summary> 52 /// <param name="propertyName"></param> 53 /// <returns></returns> 54 public object GetDynamicValue(string propertyName) 55 { 56 if (_dict.Keys.Contains(propertyName)) 57 { 58 return _dict[propertyName]; 59 } 60 return null; 61 } 62 63 public void RemoveDynamicProperty(string propertyName) 64 { 65 if (_dict.Keys.Contains(propertyName)) 66 { 67 _dict.Remove(propertyName); 68 } 69 } 70 71 /// <summary> 72 /// 重写获取动态属性 73 /// </summary> 74 /// <param name="binder"></param> 75 /// <param name="result"></param> 76 /// <returns></returns> 77 public override bool TryGetMember(GetMemberBinder binder, out object result) 78 { 79 var key = binder.Name; 80 return _dict.TryGetValue(key, out result); 81 } 82 83 /// <summary> 84 /// 重写设置动态属性 85 /// </summary> 86 /// <param name="binder"></param> 87 /// <param name="value"></param> 88 /// <returns></returns> 89 public override bool TrySetMember(SetMemberBinder binder, object value) 90 { 91 var key = binder.Name; 92 _dict[key] = value ?? default; 93 return true; 94 } 95 }
准备一个运算符枚举
1 /// <summary> 2 /// 过滤运算符枚举 3 /// </summary> 4 [Flags] 5 public enum EFilterOperator 6 { 7 [Description("=")] 8 Equal = 1, 9 10 [Description("!=")] 11 NotEqual = 2, 12 13 [Description(">")] 14 GreaterThan = 4, 15 16 [Description("<")] 17 LessThan = 8, 18 19 [Description(">=")] 20 GreaterThanOrEqual = 16, 21 22 [Description("<=")] 23 LessThanOrEqual = 32, 24 25 [Description("s")] 26 StartsWith = 64, 27 28 [Description("e")] 29 EndWith = 128, 30 31 [Description("<>")] 32 Contains = 256, 33 34 [Description("><")] 35 NotContains = 512, 36 }
准备一个表达式树辅助类
1 /// <summary> 2 /// 表达式辅助类 3 /// </summary> 4 public class ExpressionTreeHelper 5 { 6 /// <summary> 7 /// 转换属性表达式 o as UserDataProxy 8 /// </summary> 9 /// <typeparam name="T"></typeparam> 10 /// <param name="type"></param> 11 /// <returns></returns> 12 public static UnaryExpression ConvertTo<T>(ParameterExpression parameterExpression) 13 { 14 return Expression.TypeAs(parameterExpression, typeof(T)); 15 } 16 17 /// <summary> 18 /// 创建条件表达式 i.Name.Contains("xx") 19 /// </summary> 20 /// <param name="memberExpression">属性</param> 21 /// <param name="condition">条件</param> 22 /// <param name="content"></param> 23 /// <returns></returns> 24 public static Expression CreateCondition(MemberExpression memberExpression, EFilterOperator condition, string content) 25 { 26 if (content == null) 27 { 28 return null; 29 } 30 var flag = double.TryParse(content, out double num);//转换数字 能够转换是数字,不能就是文本 31 32 BinaryExpression exp;//二位运算符表达式 33 34 Expression left;//左侧表达式 35 ConstantExpression right;//右侧表达式 36 37 if (flag) 38 { 39 //把属性转换为数字 因为有的属性可能是字符串 40 left = Expression.Call(null, typeof(double).GetMethod("Parse", new Type[] { typeof(string) }), new Expression[] { memberExpression }); 41 42 //右侧的表达式 43 right = Expression.Constant(num, typeof(double)); 44 } 45 else 46 { 47 //把属性转换为字符串 48 left = Expression.Call(memberExpression, typeof(string).GetMethod("ToString", new Type[] { }), new Expression[] { }); 49 50 //右侧的表达式 51 right = Expression.Constant(content, typeof(string)); 52 } 53 54 MethodCallExpression callExp; 55 switch (condition) 56 { 57 case EFilterOperator.Equal: 58 if (!flag) 59 { 60 return null; 61 } 62 exp = Expression.Equal(left, right); 63 return exp; 64 65 case EFilterOperator.NotEqual: 66 if (!flag) 67 { 68 return null; 69 } 70 exp = Expression.NotEqual(left, right); 71 72 return exp; 73 74 case EFilterOperator.GreaterThan: 75 if (!flag) 76 { 77 return null; 78 } 79 exp = Expression.GreaterThan(left, right); 80 81 return exp; 82 83 case EFilterOperator.LessThan: 84 if (!flag) 85 { 86 return null; 87 } 88 exp = Expression.LessThan(left, right); 89 90 return exp; 91 92 case EFilterOperator.GreaterThanOrEqual: 93 if (!flag) 94 { 95 return null; 96 } 97 exp = Expression.GreaterThanOrEqual(left, right); 98 99 return exp; 100 101 case EFilterOperator.LessThanOrEqual: 102 if (!flag) 103 { 104 return null; 105 } 106 exp = Expression.LessThanOrEqual(left, right); 107 108 return exp; 109 110 case EFilterOperator.StartsWith: 111 callExp = Expression.Call(left, typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }), new Expression[] { right }); 112 113 return callExp; 114 115 case EFilterOperator.EndWith: 116 callExp = Expression.Call(left, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }), new Expression[] { right }); 117 return callExp; 118 119 case EFilterOperator.Contains: 120 121 callExp = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), new Expression[] { right }); 122 123 return callExp; 124 125 case EFilterOperator.NotContains: 126 callExp = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), new Expression[] { right }); 127 var not = Expression.Not(callExp);//取反 128 129 return not; 130 }; 131 132 return null; 133 } 134 135 /// <summary> 136 /// 获取属性表达式 137 /// </summary> 138 /// <param name="expression"></param> 139 /// <param name="propertyName"></param> 140 public static MemberExpression GetPropertyExp(Expression expression, string propertyName) 141 { 142 string orginalName; 143 144 switch (propertyName) 145 { 146 case "标识": 147 orginalName = "Guid"; 148 149 break; 150 151 case "颜色": 152 orginalName = "Color"; 153 break; 154 155 case "类型": 156 orginalName = "Type"; 157 break; 158 159 case "图层": 160 orginalName = "Layer"; 161 break; 162 163 case "名称": 164 orginalName = "Name"; 165 break; 166 167 default: 168 orginalName = propertyName; 169 break; 170 } 171 172 return Expression.Property(expression, orginalName); 173 } 174 175 /// <summary> 176 /// 合并条件表达式 177 /// </summary> 178 /// <param name="left"></param> 179 /// <param name="right"></param> 180 /// <returns></returns> 181 public static BinaryExpression JionCondition(Expression left, Expression right) 182 { 183 return Expression.AndAlso(left, right); 184 } 185 186 /// <summary> 187 /// 此处可省略 188 /// </summary> 189 /// <param name="propertyName"></param> 190 /// <param name="condition"></param> 191 /// <param name="content"></param> 192 /// <returns></returns> 193 [Obsolete("", true)] 194 private Func<UserDataProxy, bool> CreateLambda(string propertyName, EFilterOperator condition, string content) 195 { 196 string orginalName; 197 198 switch (propertyName) 199 { 200 case "标识": 201 orginalName = "Guid"; 202 203 break; 204 205 case "颜色": 206 orginalName = "Color"; 207 break; 208 209 case "类型": 210 orginalName = "Type"; 211 break; 212 213 case "图层": 214 orginalName = "Layer"; 215 break; 216 217 case "名称": 218 orginalName = "Name"; 219 break; 220 221 default: 222 orginalName = propertyName; 223 break; 224 } 225 226 var paraExp = Expression.Parameter(typeof(UserDataProxy), "u");//原始类型 227 228 var propertyExp = Expression.Property(paraExp, orginalName);//属性定义 229 230 if (content == null) 231 { 232 return null; 233 } 234 var flag = double.TryParse(content, out double num);//转换数字 能够转换是数字,不能就是文本 235 236 Expression<Func<UserDataProxy, bool>> lambda = null;//最终结果 237 BinaryExpression exp;//二位运算符表达式 238 239 Expression left;//左侧表达式 240 ConstantExpression right;//右侧表达式 241 242 if (flag) 243 { 244 left = Expression.Call(null, typeof(double).GetMethod("Parse", new Type[] { typeof(string) }), new Expression[] { propertyExp }); 245 246 right = Expression.Constant(num, typeof(double)); 247 } 248 else 249 { 250 left = Expression.Call(propertyExp, typeof(string).GetMethod("ToString", new Type[] { }), new Expression[] { });//属性转换为字符串 251 right = Expression.Constant(content, typeof(string)); 252 } 253 254 MethodCallExpression callExp; 255 switch (condition) 256 { 257 case EFilterOperator.Equal: 258 if (!flag) 259 { 260 return null; 261 } 262 exp = Expression.Equal(left, right); 263 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 264 break; 265 266 case EFilterOperator.NotEqual: 267 if (!flag) 268 { 269 return null; 270 } 271 exp = Expression.NotEqual(left, right); 272 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 273 break; 274 275 case EFilterOperator.GreaterThan: 276 if (!flag) 277 { 278 return null; 279 } 280 exp = Expression.GreaterThan(left, right); 281 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 282 break; 283 284 case EFilterOperator.LessThan: 285 if (!flag) 286 { 287 return null; 288 } 289 exp = Expression.LessThan(left, right); 290 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 291 break; 292 293 case EFilterOperator.GreaterThanOrEqual: 294 if (!flag) 295 { 296 return null; 297 } 298 exp = Expression.GreaterThanOrEqual(left, right); 299 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 300 break; 301 302 case EFilterOperator.LessThanOrEqual: 303 if (!flag) 304 { 305 return null; 306 } 307 exp = Expression.LessThanOrEqual(left, right); 308 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(exp, new ParameterExpression[] { paraExp }); 309 break; 310 311 case EFilterOperator.StartsWith: 312 callExp = Expression.Call(left, typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }), new Expression[] { right }); 313 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(callExp, new ParameterExpression[] { paraExp }); 314 break; 315 316 case EFilterOperator.EndWith: 317 callExp = Expression.Call(left, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }), new Expression[] { right }); 318 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(callExp, new ParameterExpression[] { paraExp }); 319 break; 320 321 case EFilterOperator.Contains: 322 323 callExp = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), new Expression[] { right }); 324 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(callExp, new ParameterExpression[] { paraExp }); 325 break; 326 327 case EFilterOperator.NotContains: 328 callExp = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), new Expression[] { right }); 329 lambda = Expression.Lambda<Func<UserDataProxy, bool>>(Expression.Not(callExp), new ParameterExpression[] { paraExp }); 330 break; 331 }; 332 333 return lambda.Compile(); 334 } 335 }
运行测试
1 internal class Program 2 { 3 public static Func<object, bool> Show() 4 { 5 return null; 6 } 7 8 private static void Main(string[] args) 9 { 10 var list = new List<object>() 11 { 12 new UserDataProxy(){Color="红色",Name="王义夫",Length="120"}, 13 new UserDataProxy(){Color="绿色",Name="王受人",Length="2120"}, 14 new UserDataProxy(){Color="蓝色",Name="王马子",Length="920"}, 15 new UserDataProxy(){Color="白色",Name="张三义",Length="1120"}, 16 new UserDataProxy(){Color="紫色",Name="里义夫",Length="1120"}, 17 new UserDataProxy(){Color="红色",Name="王义夫",Length="1020"}, 18 new UserDataProxy(){Color="红色",Name="王首任",Length="750"}, 19 new UserDataProxy(){Color="红色",Name="李义夫",Length="1210"}, 20 new UserDataProxy(){Color="红色",Name="勇义夫",Length="1110"}, 21 }; 22 23 Console.WriteLine($"过滤之前\n"); 24 list.ForEach(user => 25 { 26 var uu = user as UserDataProxy; 27 28 Console.WriteLine($"Color:{uu.Color},Length:{uu.Length},Name:{uu.Name}"); 29 }); 30 31 var collection = CollectionViewSource.GetDefaultView(list); 32 33 //第一个条件 34 var p1 = "Color"; 35 var c1 = EFilterOperator.Contains; 36 var t1 = "红"; 37 38 //第二个条件 39 var p2 = "Length"; 40 var c2 = EFilterOperator.GreaterThan; 41 var t2 = "1000"; 42 43 //第三个条件 44 var p3 = "Name"; 45 var c3 = EFilterOperator.NotContains; 46 var t3 = "王"; 47 48 //生成条件1 49 var o = Expression.Parameter(typeof(object)); 50 51 var objExp = ExpressionTreeHelper.ConvertTo<UserDataProxy>(o); 52 53 var m1 = ExpressionTreeHelper.GetPropertyExp(objExp, p1); 54 55 var condition1 = ExpressionTreeHelper.CreateCondition(m1, c1, t1); 56 57 //生成条件2 58 var m2 = ExpressionTreeHelper.GetPropertyExp(objExp, p2); 59 60 var condition2 = ExpressionTreeHelper.CreateCondition(m2, c2, t2); 61 62 //生成条件3 63 var m3 = ExpressionTreeHelper.GetPropertyExp(objExp, p3); 64 65 var condition3 = ExpressionTreeHelper.CreateCondition(m3, c3, t3); 66 67 //合并条件 68 var r1 = ExpressionTreeHelper.JionCondition(condition1, condition2);//第一次过滤 69 70 //r1 = ExpressionTreeHelper.JionCondition(r1, condition3);//添加条件后过滤 71 72 var s = Expression.Lambda<Predicate<object>>(r1, o);//创建Lambda表达式 73 74 var func = s.Compile();//编译成委托 75 76 if (func != null) 77 { 78 //属性可能为null,在此处抛出异常 79 try 80 { 81 collection.Filter = func; 82 collection.Refresh(); 83 } 84 catch (Exception ex) 85 { 86 Console.WriteLine($"{ex.Message}"); 87 } 88 } 89 90 Console.WriteLine($"过滤之后\n"); 91 foreach (var item in collection) 92 { 93 var u = item as UserDataProxy; 94 95 Console.WriteLine($"Color:{u.Color},Length:{u.Length},Name:{u.Name}"); 96 } 97 } 98 }
过滤结果