DevExpress Winforms使用技巧教程:掌握Filter Editor(一)
下载DevExpress v19.2完整版 DevExpress v19.2汉化资源获取
DevExpress Winforms Controls 内置140多个UI控件和库,完美构建流畅、美观且易于使用的应用程序。想要体验?点击下载>>
DevExpress WinForms安装附带两个允许最终用户构建过滤器查询的控件:提供GUI的Filter控件和将Filter控件与基于文本输入的面板组合在一起的Filter Editor控件。WinForms中,大多数数据感知控件都使用这些组件,但是您也可以将其包含在自己的表单中,并根据需要将其绑定到数据感知控件中。
为了说明这一点,下面是带有Filter Editor的数据网格,用户可以单击过滤器面板中的Edit Filter按钮来调出Filter Editor,并且由于属性DefaultFilterEditorView设置为TextAndVisual,因此可以看到Filter Editor Control的文本面板。
在下图中,您可以看到两个控件中可用的一些标准功能,包括“小于或等于”,“大于或等于”,“今天”,“昨天”以及许多其他功能。Filter控件和Filter Editor控件均提供多种功能供您选择,可用功能集因要为其构建表达式的数据字段的类型而异。
自定义函数
在某些情况下,标准函数集还不够。技术团队在处理大量技术支持问题发现,查找是最常见需要的自定义函数。以下是三种最受欢迎的方案:
- 标准函数的倒置,可以在filter editor中手动应用这些,但是对于频繁使用,自定义函数更方便。
- 表示复杂表达式的标准函数组合的函数。 例如,Within Days of X函数可能包含行,其中字段值在给定日期之前或之后的N天内,这省去了用户在两个不同日期之间配置标准函数的工作量。
- 自定义DateTime函数,例如Is Weekend,N Days Ago等。
从v19.1开始,Filter Editor控件和Filter控件完全支持自定义函数,从而可以轻松实现上述方案和许多其他方案。
技术基础
自定义函数是实现接口ICustomFunctionDisplayAttributes的类,请注意如果需要服务器端对自定义函数的处理,则可以额外实现ICustomFunctionOperatorFormattable接口,但是在本文范围内,我们仅关注ICustomFunctionDisplayAttributes。
这些是接口实现所需的方法和属性:
- Name - 您用来从代码中引用自定义函数的技术功能名称
- DisplayName - GUI中显示的可读函数名称。 例如,名称为NotStartsWith的函数的DisplayName可能不是开头的
- Image - Filter Control菜单中为该函数显示的图标,该属性类型为Object,但是下面的示例显示了如何使用现有的标准图像,也可以分配图像对象
- Description - 用户在Filter Editor控件的文本面板中编辑表达式时,在弹出提示中的函数描述
- Category - 的函数类别,如果您打算仅将函数用于过滤器,则这无关紧要
- MinOperatorCount, MaxOperatorCount, IsValidOperandCount - 该函数支持运算符数量,对于Filter和Filter Editor控件,所有三个值可以相等。 如果计划在中使用函数,则可以灵活地支持可变数量的运算符。
- IsValidOperandType - 调用每个操作数来检查是否具有有效的类型,仅检查第一个操作数的筛选器
- ResultType - 函数的返回值类型,Filter控件仅显示具有布尔结果类型的函数
- Evaluate - 该函数在函数每次对一个数据字段求值时都会调用的方法,值在操作数数组中传递。 返回true包括相关行,返回false排除相关行。
最后,我们建议添加两个静态便利函数Register和Unregister。 这是一个可选步骤,但是实现很简单(请参见下文),并且它们以CriteriaOperator类型调用现有的帮助器。
示例
供您参考,下面是三个示例,它们涵盖了上面提到的三个最需要的方案。 第一个自定义函数称为NotBeginsWith,它是对标准函数BeginsWith的取反。
public class NotBeginsWithFunction : ICustomFunctionDisplayAttributes { public const string FunctionName = "NotBeginsWith"; static readonly NotBeginsWithFunction instance = new NotBeginsWithFunction(); public static void Register() { CriteriaOperator.RegisterCustomFunction(instance); } public static bool Unregister() { return CriteriaOperator.UnregisterCustomFunction(instance); } public string Name => FunctionName; public string DisplayName => "Does not begin with"; public object Image => "FontSizeDecrease;Office2013"; public string Description => "Hides records when the field begins with the given value"; public FunctionCategory Category => FunctionCategory.Text; public int MinOperandCount => 2; public int MaxOperandCount => 2; public bool IsValidOperandCount(int count) => count == 2; public bool IsValidOperandType(int operandIndex, int operandCount, Type type) => type == typeof(string); public Type ResultType(params Type[] operands) => typeof(bool); public object Evaluate(params object[] operands) { if(operands[0] != null && operands[1] != null) { string str1 = operands[0].ToString(); string str2 = operands[1].ToString(); return !str1.StartsWith(str2, StringComparison.InvariantCultureIgnoreCase); } return false; } }
这是第二个自定义函数InternalDaysOfToday,用于检查DateTime值是否在今天-N天和今天+ N天的时间范围内。
public class WithinDaysOfTodayFunction : ICustomFunctionDisplayAttributes { public const string FunctionName = "WithinDaysOfToday"; static readonly WithinDaysOfTodayFunction instance = new WithinDaysOfTodayFunction(); public static void Register() { CriteriaOperator.RegisterCustomFunction(instance); } public static bool Unregister() { return CriteriaOperator.UnregisterCustomFunction(instance); } public string Name => FunctionName; public string DisplayName => "Within days of today"; public object Image => "SwitchTimeScalesTo;Size16x16;Colored"; public string Description => "Shows records when the field value within X days of today"; public FunctionCategory Category => FunctionCategory.DateTime; public int MinOperandCount => 2; public int MaxOperandCount => 2; public bool IsValidOperandCount(int count) => count == 2; public bool IsValidOperandType(int operandIndex, int operandCount, Type type) => operandIndex == 0 && type == typeof(DateTime) || operandIndex == 1 && type == typeof(int); public Type ResultType(params Type[] operands) => return typeof(bool); public object Evaluate(params object[] operands) { DateTime dt = Convert.ToDateTime(operands[0]); int days = Convert.ToInt32(operands[1]); DateTime start = DateTime.Today.AddDays(-days); DateTime end = DateTime.Today.AddDays(days); return dt >= start && dt <= end; } }
最后,IsWeekend测试DateTime值是星期六还是星期天。
public class IsWeekendFunction : ICustomFunctionDisplayAttributes { public const string FunctionName = "IsWeekend"; static readonly IsWeekendFunction instance = new IsWeekendFunction(); public static void Register() { CriteriaOperator.RegisterCustomFunction(instance); } public static bool Unregister() { return CriteriaOperator.UnregisterCustomFunction(instance); } public string Name => FunctionName; public string DisplayName => "Is weekend"; public object Image => "DayView;Office2013"; public string Description => "Shows records when the field value is on Saturday or Sunday"; public FunctionCategory Category => FunctionCategory.DateTime; public int MinOperandCount => 1; public int MaxOperandCount => 1; public bool IsValidOperandCount(int count) => count == 1; public bool IsValidOperandType(int operandIndex, int operandCount, Type type) => type == typeof(DateTime); public Type ResultType(params Type[] operands) => typeof(bool); public object Evaluate(params object[] operands) { DateTime dt = Convert.ToDateTime(operands[0]); return dt.DayOfWeek == DayOfWeek.Sunday || dt.DayOfWeek == DayOfWeek.Saturday; } }
DevExpress v19.2线上公开课即将开课,前10名免费参与哦~
DevExpress技术交流群:540330292 欢迎一起进群讨论
扫描关注DevExpress中文网微信公众号,及时获取最新动态及最新资讯