程序化的过滤
RadGridView提供了一个丰富的API,允许您以编程方式进行过滤。最终用户可以通过UI实现的所有功能也可以通过使用代码隐藏API来实现。在本文中,我们将讨论:
列过滤
有时开发人员可能想要预过滤RadGridView,这样最终用户就可以使用已经过滤过的网格。当然,RadGridView的UI必须与编程定义的过滤标准一致。要实现这一点,必须使用IColumnFilterDescriptor合同。这是列可以“理解”并在其过滤UI中反映的唯一契约。
过滤单柱
IColumnFilterDescriptor接口模仿了默认的结构弹出式过滤控件.它像过滤控件一样有两个部分——不同的值和字段过滤器。要获得IColumnFilterDescriptor,必须从相应的列中访问它ColumnFilterDescriptor财产。一旦有了对它的引用,就可以设置它的属性。在IColumnFilterDescriptor上设置属性与最终用户使用鼠标和键盘通过UI执行相应的操作相同。
如果您希望一次调整许多属性,而不会在每个属性之后触发数据引擎更新,那么暂时暂停IColumnFilterDescriptor的通知,以编程方式进行过滤,最后恢复通知可能是一个好主意。当您恢复通知时,数据引擎将计算新的过滤器。示例1演示如何以编程方式筛选单个列。
示例1:以编程方式筛选单个列
Telerik.Windows.Controls.GridViewColumn countryColumn = this.radGridView.Columns["国家"];telerink . windows . controls . gridview . icolumnfilterdescriptor countryFilter = countryColumn.ColumnFilterDescriptor;//暂停通知以避免多个数据引擎更新//这就像最终用户通过UI选择一个不同的值。countryFilter.DistinctFilter.AddDistinctValue(“波兰”);countryFilter.DistinctFilter.AddDistinctValue(西班牙);countryFilter.DistinctFilter.AddDistinctValue(“乌兹别克斯坦”);countryFilter.DistinctFilter.AddDistinctValue(“荷兰”);countryFilter.DistinctFilter.AddDistinctValue(“奥地利”);countryFilter.DistinctFilter.AddDistinctValue(“芬兰”); countryFilter.DistinctFilter.AddDistinctValue("Pakistan"); // This is the same as the end user configuring the upper field filter. countryFilter.FieldFilter.Filter1.Operator = Telerik.Windows.Data.FilterOperator.Contains; countryFilter.FieldFilter.Filter1.Value = "land"; countryFilter.FieldFilter.Filter1.IsCaseSensitive = true; // This is the same as the end user changing the logical operator between the two field filters. countryFilter.FieldFilter.LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.Or; // This is the same as the end user configuring the lower field filter. countryFilter.FieldFilter.Filter2.Operator = Telerik.Windows.Data.FilterOperator.Contains; countryFilter.FieldFilter.Filter2.Value = "stan"; countryFilter.FieldFilter.Filter2.IsCaseSensitive = true; // Resume the notifications to force the data engine to update the filter. countryFilter.ResumeNotifications();
Dim countryColumn As telerick . windows . controls . gridviewcolumn = Me.radGridView.Columns("Country")暂停通知以避免多个数据引擎更新这与最终用户通过UI选择不同的值相同。countryFilter.DistinctFilter.AddDistinctValue(“波兰”)countryFilter.DistinctFilter.AddDistinctValue(“西班牙”)countryFilter.DistinctFilter.AddDistinctValue(“乌兹别克斯坦”)countryFilter.DistinctFilter.AddDistinctValue(“荷兰”)countryFilter.DistinctFilter.AddDistinctValue(“奥地利”)countryFilter.DistinctFilter.AddDistinctValue(“芬兰”)countryFilter.DistinctFilter.AddDistinctValue(“巴基斯坦”)'这与最终用户配置上层字段筛选器相同。countryFilter.FieldFilter.Filter1。[Operator] = telerik . windows . data . filteroperator .包含countryFilter.FieldFilter.Filter1。值= "land" countryFilter.FieldFilter.Filter1。IsCaseSensitive= True ' This is the same as the end user changing the logical operator between the two field filters. countryFilter.FieldFilter.LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.[Or] ' This is the same as the end user configuring the lower field filter. countryFilter.FieldFilter.Filter2.[Operator] = Telerik.Windows.Data.FilterOperator.Contains countryFilter.FieldFilter.Filter2.Value = "stan" countryFilter.FieldFilter.Filter2.IsCaseSensitive = True ' Resume the notifications to force the data engine to update the filter. countryFilter.ResumeNotifications()
图1:预过滤的RadGridView
的DistinctFilter对象也有一个方法RemoveDistinctValue它的反义词是什么AddDistinctValue.
注意,如果你在它的筛选行模式下使用RadGridView,你只需要使用FieldFilter。Filter1对象。过滤器行仅显示FieldFilter中存储的内容。Filter1 -它既没有不同的值也没有Filter2并且会简单地忽略它们。
清除单列过滤器
如果希望以编程方式从列中清除现有筛选器,只需调用ClearFilters各自列的方法。您不需要挂起或恢复任何操作,因为这本身就是一个批处理操作。
如果您添加了一个FilterDescriptor而不是IColumnFilterDescriptor,那么您需要清除FilterDescriptors集合。
过滤多列
如果你想一次预过滤多个列,而不是在每个列之后触发数据引擎更新,你可以遵循相同的暂停/恢复模式,但这次使用RadGridView的模式FilterDescriptors收集。以下是如何通过单个批处理操作过滤多个列:
示例2:以编程方式筛选多个列
this.radGridView.FilterDescriptors.SuspendNotifications ();/ /……在这里过滤尽可能多的列…this.radGridView.FilterDescriptors.ResumeNotifications ();
Me.radGridView.FilterDescriptors.SuspendNotifications ()“…在这里过滤尽可能多的列…Me.radGridView.FilterDescriptors.ResumeNotifications ()
清除多个列过滤器
清除多个列筛选器也是通过使用暂停/恢复模式完成的。示例3演示如何清除所有列筛选器。
例3:清除多个列筛选器
this.radGridView.FilterDescriptors.SuspendNotifications ();foreach (Telerik.Windows.Controls。this.radGridView.Columns) {column. clearfilters ();} this.radGridView.FilterDescriptors.ResumeNotifications ();
Me.radGridView.FilterDescriptors.SuspendNotifications() For Each column As Telerik.Windows.Controls.GridViewColumn In Me.radGridView.Columns column. clearfilters () Next me . radgridview . filterdescriptors . resumenotifizations ()
自定义筛选
IColumnFilterDescriptor有其局限性,因为它模仿了弹出式过滤控件的UI结构。然而,有时更复杂的过滤器必须以编程的方式应用到RadGridView。虽然这些过滤器不能反映在UI中,因为它们不遵循IColumnFilterDescriptor契约,但它们可以非常复杂。为了过滤RadGridView,你必须添加一个IFilterDescriptor实例的FilterDescriptors集合属性。
IFilterDescriptor
该接口是过滤条件树的构建块。它只有一个方法叫做CreateFilterExpression.通常情况下,您不必自己实现它,因为我们已经为所有常见情况提供了默认实现。如果你有一个自定义的需求,而我们的默认实现无法满足,你总是可以实现这个接口并返回任何有效的LINQ表达式,然后我们的数据引擎在组合过滤器时使用它。关于实现此接口的更多信息,您可以从中学习这个高级主题.
IFilterDescriptor接口有两个主要实现-FilterDescriptor和CompositeFilterDescriptor.这两个类允许您通过简单地设置它们的属性来构建任意复杂的过滤条件树。
FilterDescriptor
FilterDescriptor类表示筛选条件树中的叶终端节点。它表达了一个过滤条件,并具有以下重要属性:
成员:指定要筛选的属性的名称。这是左边的操作数。
操作符:指定要使用的比较运算符。
价值:指定成员将与之比较的值。这是右边的操作数。
IsCaseSensitive:用于MemberType的值,以确定比较是否应该区分大小写。
MemberType:指定实际成员的类型是多少。只有当数据引擎不能自动发现类型时,才需要设置该参数。
典型的FilterDescriptor可能是这样的:
例4:自定义的FilterDescriptor
//把所有叫约翰的人都给我。Telerik.Windows.Data.FilterDescriptor fd = new Telerik.Windows.Data.FilterDescriptor();fd。Member = "FirstName";fd。Operator = Telerik.Windows.Data.FilterOperator.IsEqualTo;fd。Value = "John";fd。IsCaseSensitive = true; // In most cases the data engine will discover this automatically so you do not need to set it. fd.MemberType = typeof(string);
凡叫约翰的,都给我来。Dim fd As New Telerik.Windows.Data.FilterDescriptor() fd。fd. Member = "FirstName"[Operator] = Telerik.Windows.Data.FilterOperator.IsEqualTo fd.]fd. Value = "John"。IsCaseSensitive= True ' In most cases the data engine will discover this automatically so you do not need to set it. fd.MemberType = GetType(String)
当选择操作符,你必须确保各自的MemberType支持此操作符。例如,不能使用包含如果你的MemberType是Int32因为数据引擎会崩溃。下面是一个过滤器操作符和支持它们的类型的表。
表1:过滤操作符和支持它们的类型
运营商 | 类型 |
---|---|
IsEqualTo, IsNotEqualTo | 所有可过滤类型 |
开始与,结束与,包含,不包含,IsContainedIn, IsNotContainedIn, IsEmpty, IsNotEmpty | 字符串 |
IsLessThan, IsLessThanOrEqualTo, IsGreaterThan, IsGreaterThanOrEqualTo | 数字类型、DateTime、TimeSpan,所有重载这些操作符的类型 |
IsNull, IsNotNull | 所有可过滤的可空类型 |
你可以本地化那些字符串。对于本地化字符串的完整列表,请检查这个如何切入主题.
为了帮助您理解数据引擎是如何使用这个FilterDescriptor的,让我们用上面创建的一个实例给出一个实际的例子。数据引擎将根据从FilterDescriptor实例中读取的信息构建一个LINQ表达式。然后,它将对RadGridView的源集合的查询提供程序执行此查询。下面是这个FilterDescriptor在伪代码中的表达式:
例5:生成的LINQ表达式
人。其中(person => person。FirstName == "John");
people.Where(函数(人)的人。FirstName = "John")
数据引擎在运行时构建、编译和执行这个LINQ表达式。如果存储在FilterDescriptor中的信息不一致,您将在运行时收到一个异常。
有一个特殊的单例值叫做FilterDesciptor。UnsetValue.如果将此特殊值赋给价值属性的FilterDescriptor,你有效地关闭了它。换句话说,当数据引擎遇到值等于FilterDesciptor的FilterDescriptor时。UnsetValue它会直接忽略它。当您只是想打开或关闭一个FilterDescriptor,而不想不断地附加或分离它时,这个特殊值可能非常有用。您可以通过读取FilterDescriptor当前是否处于活动状态IsActive财产。
设置FilterDescriptor的区域性
的R2 2018(2018.1.226最新内部构建)特定的区域性可以应用到FilterDescriptor。这是通过接受System.Globalization.CultureInfo参数的附加构造函数来完成的。
例6:设置FilterDescriptor的区域性
FilterDescriptor description = new FilterDescriptor("Name", FilterOperator. FilterDescriptor)IsNotEqualTo, "利物浦",new CultureInfo("fr-FR"));
私有描述符As FilterDescriptor = New FilterDescriptor("Name", FilterOperator. FilterDescriptor)。IsNotEqualTo, "利物浦",New CultureInfo("fr-FR"))
CompositeFilterDescriptor
的CompositeFilterDescriptor只不过是其他ifilterdescriptor与逻辑运算符(和/或).它的子属性存储在FilterDescriptors属性中,可以是IFilterDescriptor接口的任何有效实现,该接口允许您构造无限的过滤条件树。子过滤器与LogicalOperator可以是“与”也可以是“或”。
想象一下,我们只希望得到年龄在18到60岁之间的西班牙人。示例5展示了如何实现这一目标:
例7:创建一个CompositeFilterDescriptor
Telerik.Windows.Data. filterdescriptor olderThan18Filter = new Telerik.Windows.Data。Telerik.Windows.Data.FilterOperator FilterDescriptor(“时代”。IsGreaterThanOrEqualTo 18);Telerik.Windows.Data. filterdescriptor youngerThan60Filter = new Telerik.Windows.Data。Telerik.Windows.Data.FilterOperator FilterDescriptor(“时代”。IsLessThan、60);Telerik.Windows.Data.CompositeFilterDescriptor ageFilter = new Telerik.Windows.Data.CompositeFilterDescriptor();ageFilter.FilterDescriptors.Add (olderThan18Filter);ageFilter.FilterDescriptors.Add (youngerThan60Filter);ageFilter。LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.And;Telerik.Windows.Data. filterdescriptor liveInSpainFilter = new Telerik.Windows.Data。Telerik.Windows.Data.FilterOperator FilterDescriptor(“国家”。IsEqualTo,“西班牙”);Telerik.Windows.Data.CompositeFilterDescriptor mainFilter = new Telerik.Windows.Data.CompositeFilterDescriptor();mainFilter.FilterDescriptors.Add (ageFilter); mainFilter.FilterDescriptors.Add(liveInSpainFilter); mainFilter.LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.And; this.radGridView.FilterDescriptors.Add(mainFilter);
凡叫约翰的,都给我来。Dim olderThan18Filter As New Telerik.Windows.Data。FilterDescriptor("Age", Telerik.Windows.Data.FilterOperator.IsGreaterThanOrEqualTo, 18) Dim youngerThan60Filter As New Telerik.Windows.Data.FilterDescriptor("Age", Telerik.Windows.Data.FilterOperator.IsLessThan, 60) Dim ageFilter As New Telerik.Windows.Data.CompositeFilterDescriptor() ageFilter.FilterDescriptors.Add(olderThan18Filter) ageFilter.FilterDescriptors.Add(youngerThan60Filter) ageFilter.LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.[And] Dim liveInSpainFilter As New Telerik.Windows.Data.FilterDescriptor("Country", Telerik.Windows.Data.FilterOperator.IsEqualTo, "Spain") Dim mainFilter As New Telerik.Windows.Data.CompositeFilterDescriptor() mainFilter.FilterDescriptors.Add(ageFilter) mainFilter.FilterDescriptors.Add(liveInSpainFilter) mainFilter.LogicalOperator = Telerik.Windows.Data.FilterCompositionLogicalOperator.[And] Me.radGridView.FilterDescriptors.Add(mainFilter)
所以最后你会得到如下的过滤条件树:
图2:过滤条件树概念
数据引擎将在伪代码中生成类似的东西:
例8:生成的LINQ表达式
人。其中(person => (person。国家==“西班牙”&&(人。年龄>= 18 &&人。年龄< 60岁)));
people.Where(函数(人)(人。国家=“西班牙”和also(人。年龄>= 18,也是人。年龄< 60岁))
您在Where子句中看到的lambda表达式是基于我们定义的描述符构建的。但是,如果您自己实现IFilterDescriptor,则可以提供数据引擎使用的任何类型的自定义表达式,只要它是有效的,并且可以在运行时编译和执行。
正如您可能已经猜到的那样,用于列筛选的IColumnFilterDescriptor也在底层使用这些类来构造其表达式。遵守界面契约可以确保您只能添加可以在固定布局过滤UI中显示的内容。在内部深处,IColumnFilterDescriptor看起来像这样:
图3:ColumnFilterDescriptor Tree
注意这个层次结构是如何与Popup过滤控件布局相同的。通过IColumnFilterDescriptor接口,可以确保您不能随机添加Popup过滤控件不能正确显示的条件。
上的一些示例代码编程过滤演示.