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中文網微信公眾號,及時獲取最新動態及最新資訊
