10.3 QueryExtender控件
QueryExtender控件是ASP.NET 4新增加的一个数据筛选控件,它用于为从数据源检索的数据创建筛选器,并且在数据源中不使用显式Where子句。可以将它添加到EntityDataSource控件或LinqDataSource控件以筛选这些控件返回的数据。它依赖于LINQ,但无须了解如何编写LINQ查询即可使用该查询扩展程序。利用它,可以简单地通过声明性语法筛选网页标记中的数据。除此之外,它还支持ASP.NET动态数据专用的表达式。
QueryExtender控件支持多种可用于筛选数据的选项,即支持搜索字符串、搜索指定范围内的值、将表中的属性值与指定的值进行比较、排序和自定义查询等。下面就来详细阐述如何使用它进行数据筛选。
10.3.1 SearchExpession
SearchExpression类将一个或多个字段中的指定字符串与提供的值作比较,它执行“开头为”、“包含”或“结尾为”搜索。例如,可以向文本框控件中输入文本,并使用该表达式搜索从数据源控件返回的列中的该文本。
在使用SearchExpression时,必须为它的SearchType属性和DataFields属性指定值,以指明要执行的搜索类型以及要搜索的数据字段。其中,SearchType属性使用的SearchType枚举包含要在SearchExpression类的实例中使用的搜索类型。枚举值为:
❑StartsWith:指示的字段中的任意位置开始的搜索。
❑Contains:指示从一个字段开头开始的搜索。
❑EndsWith:指示在字段结尾的搜索。
因为QueryExtender控件依赖于LINQ。所以要在QueryExtender控件中使用SearchExpression进行数据搜索,还需要创建一个.dbml文件。创建的示例Employees.dbml文件如图10-21所示。
创建好Employees.dbml文件之后,就可以通过在页面中使用ASP.NET控件来提供要搜索的值。为此,还需要将SearchExpression对象中ControlParameter类的ControlID属性设置为该ASP.NET控件的ID。
图 10-21 示例Employees.dbml文件
下面的示例程序演示了如何在ASP.NET 4数据库的Employee数据表的EmployeeName列中,搜索以SearchTextBox控件中指定的字符串开头的员工信息。从LinqDataSource控件返回的结果显示在GridView控件中,如代码清单10-3所示。
代码清单10-3 SearchExpressionTest.aspx
<form id="form1"runat="server">
搜索员工姓名:
<asp:TextBox ID="SearchTextBox"runat="server"/>
<asp:Button ID="Button1"runat="server"Text="搜索"/>
<br/><br/>
<asp:LinqDataSource ID="LinqDataSource1"
TableName="Employees"runat="server"
ContextTypeName="_10_2.EmployeesDataContext"
EntityTypeName=""Select="new(employeeid, employeename,
department, address, email, workdate)">
</asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1"runat="server"
TargetControlID="LinqDataSource1">
<asp:SearchExpression SearchType="StartsWith"
DataFields="EmployeeName">
<asp:ControlParameter ControlID="SearchTextBox"/>
</asp:SearchExpression>
</asp:QueryExtender>
<asp:GridView ID="GridView1"runat="server"Width="100%"
DataSourceID="LinqDataSource1"AllowPaging="True"
AutoGenerateColumns="False"DataKeyNames="employeeid">
<Columns>
<asp:BoundField DataField="employeeid"HeaderText="编号"
ReadOnly="True"SortExpression="employeeid"/>
<asp:BoundField DataField="employeename"HeaderText="姓名"
SortExpression="employeename"/>
<asp:BoundField DataField="department"HeaderText="部门"
SortExpression="department"/>
<asp:BoundField DataField="address"HeaderText="住址"
SortExpression="address"/>
<asp:BoundField DataField="email"HeaderText="邮箱"
SortExpression="email"/>
<asp:BoundField DataField="workdate"HeaderText="工作时间"
SortExpression="workdate"/>
</Columns>
</asp:GridView>
</form>
示例运行结果如图10-22所示。
图 10-22 示例运行结果
还需要说明的是,如果在QueryExtender控件中使用的LINQ提供程序支持区分大小写,还可以使用SearchExpression的ComparisonType属性启用或禁用区分大小写。
10.3.2 RangeExpression
RangeExpression类与SearchExpression类相似,不同之处在于RangeExpression类使用了一对值来定义范围,以确定列中的值是否在指定的最小值和最大值之间。例如,可以在表的“单价”列中搜索介于10元和100元之间的值。
在使用RangeExpression时,必须使用DataField属性指定要搜索的列;使用MinType属性指定是否在搜索结果中包括或排除最小值;使用MaxType属性指定是否包括或排除最大值。其中,MinType与MaxType属性的值包括Inclusive、Exclusive和None。当MinType属性或MaxType属性设置为Inclusive时,范围的最大值和最小值包括在搜索结果中,这相当于执行一个>=或<=运算;Exclusive字段等效于>或<运算;None将不会对范围施加任何限制。最大值和最小值可以通过在页面中使用ASP.NET控件来指定,然后将该值作为ControlParameter控件中的参数传递到QueryExtender控件。
下面的示例程序演示了如何在ASP.NET 4数据库的Employee数据表的EmployeeID列中,搜索员工编号位于FromTextBox和ToTextBox文本框指定的范围内的员工信息。其中,筛选器包括最小值,但不包括结果中的最大值。最后,从LinqDataSource控件返回的结果显示在GridView控件中,如代码清单10-4所示。
代码清单10-4 RangeExpressionTest.aspx
<form id="form1"runat="server">
搜索员工编号:
<asp:TextBox ID="FromTextBox"runat="server"></asp:TextBox>
到
<asp:TextBox ID="ToTextBox"runat="server"></asp:TextBox>
<asp:Button ID="Button1"runat="server"Text="搜索"/>
<br/>
<br/>
<asp:LinqDataSource ID="LinqDataSource1"
TableName="Employees"runat="server"
ContextTypeName="_10_2.EmployeesDataContext"
EntityTypeName=""Select="new(employeeid, employeename,
department, address, email, workdate)">
</asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1"runat="server"
TargetControlID="LinqDataSource1">
<asp:RangeExpression DataField="employeeid"
MinType="Inclusive"MaxType="Exclusive">
<asp:ControlParameter ControlID="FromTextBox"/>
<asp:ControlParameter ControlID="ToTextBox"/>
</asp:RangeExpression>
</asp:QueryExtender>
<asp:GridView ID="GridView1"runat="server"Width="100%"
DataSourceID="LinqDataSource1"
AllowPaging="True"AutoGenerateColumns="False"
DataKeyNames="employeeid">
<Columns>
<asp:BoundField DataField="employeeid"HeaderText="编号"
ReadOnly="True"SortExpression="employeeid"/>
<asp:BoundField DataField="employeename"HeaderText="姓名"
SortExpression="employeename"/>
<asp:BoundField DataField="department"HeaderText="部门"
SortExpression="department"/>
<asp:BoundField DataField="address"HeaderText="住址"
SortExpression="address"/>
<asp:BoundField DataField="email"HeaderText="邮箱"
SortExpression="email"/>
<asp:BoundField DataField="workdate"HeaderText="工作时间"
SortExpression="workdate"/>
</Columns>
</asp:GridView>
</form>
示例运行结果如图10-23所示。
图 10-23 示例运行结果
10.3.3 PropertyExpression
相对于其他表达式类,Pro perty-Expression类比较简单,它将列的属性值与指定的值进行比较。它为每个参数的值和IQueryable数据对象的相应属性创建一个相等(==)比较。如果提供多个参数,将使用逻辑AND运算符组合这些参数,包含空值的参数不添加到Where子句中。
下面的示例程序演示了如何在ASP.NET 4数据库的Employee数据表的EmployeeName列中,搜索员工姓名等于SearchTextBox文本框中指定的值的员工信息。从LinqDataSource控件返回的结果显示在GridView控件中,如代码清单10-5所示。
代码清单10-5 PropertyExpressionTest.aspx
<form id="form1"runat="server">
搜索员工姓名:
<asp:TextBox ID="SearchTextBox"runat="server"/>
<asp:Button ID="Button1"runat="server"Text="搜索"/>
<br/>
<br/>
<asp:LinqDataSource ID="LinqDataSource1"
TableName="Employees"runat="server"
ContextTypeName="_10_2.EmployeesDataContext"
EntityTypeName=""Select="new(employeeid, employeename,
department, address, email, workdate)">
</asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1"runat="server"
TargetControlID="LinqDataSource1">
<asp:PropertyExpression>
<asp:ControlParameter ControlID="SearchTextBox"
Name="employeename"/>
</asp:PropertyExpression>
</asp:QueryExtender>
<asp:GridView ID="GridView1"runat="server"Width="100%"
DataSourceID="LinqDataSource1"
AllowPaging="True"AutoGenerateColumns="False"
DataKeyNames="employeeid">
<Columns>
<asp:BoundField DataField="employeeid"HeaderText="编号"
ReadOnly="True"SortExpression="employeeid"/>
<asp:BoundField DataField="employeename"HeaderText="姓名"
SortExpression="employeename"/>
<asp:BoundField DataField="department"HeaderText="部门"
SortExpression="department"/>
<asp:BoundField DataField="address"HeaderText="住址"
SortExpression="address"/>
<asp:BoundField DataField="email"HeaderText="邮箱"
SortExpression="email"/>
<asp:BoundField DataField="workdate"HeaderText="工作时间"
SortExpression="workdate"/>
</Columns>
</asp:GridView>
</form>
示例运行结果如图10-24所示。
图 10-24 示例运行结果
10.3.4 OrderByExpression
前面讲过,QueryExtender控件支持多种可用于筛选数据的选项。但在使用筛选器选项之后,还可以使用OrderByExpression对象来排序数据。其中,OrderByExpression类可以按指定列和排序方向对数据进行排序。
在使用OrderByExpression时,可以使用它的DataField属性指定要排序的数据字段;使用Direction属性指定排序方向。OrderByExpression对象应用到数据源后,还可以使用ThenBy表达式对另一个数据字段执行后续排序。
下面的示例程序演示了如何在ASP.NET 4数据库的Employee数据表的Department列中,搜索员工部门等于SearchTextBox文本框中指定的字符串开头的员工信息。其中,OrderByExpression对象按Workdate数据字段的降序和EmployeeID字段的升序对数据排序。最后从LinqDataSource控件返回的结果显示在GridView控件中。如代码清单10-6所示。
代码清单10-6 OrderByExpressionTest.aspx
<form id="form1"runat="server">
搜索员工部门:
<asp:TextBox ID="SearchTextBox"runat="server"/>
<asp:Button ID="Button1"runat="server"Text="搜索"/>
<br/>
<br/>
<asp:LinqDataSource ID="LinqDataSource1"TableName="Employees"
runat="server"ContextTypeName="_10_2.EmployeesDataContext"
EntityTypeName=""Select="new(employeeid, employeename,
department, address, email, workdate)">
</asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1"runat="server"
TargetControlID="LinqDataSource1">
<asp:SearchExpression SearchType="StartsWith"
DataFields="department">
<asp:ControlParameter ControlID="SearchTextBox"/>
</asp:SearchExpression>
<asp:OrderByExpression DataField="workdate"
Direction="Descending">
<asp:ThenBy DataField="employeeid"
Direction="Ascending"/>
</asp:OrderByExpression>
</asp:QueryExtender>
<asp:GridView ID="GridView1"runat="server"Width="100%"
DataSourceID="LinqDataSource1"
AllowPaging="True"AutoGenerateColumns="False"
DataKeyNames="employeeid">
<Columns>
<asp:BoundField DataField="employeeid"HeaderText="编号"
ReadOnly="True"SortExpression="employeeid"/>
<asp:BoundField DataField="employeename"HeaderText="姓名"
SortExpression="employeename"/>
<asp:BoundField DataField="department"HeaderText="部门"
SortExpression="department"/>
<asp:BoundField DataField="address"HeaderText="住址"
SortExpression="address"/>
<asp:BoundField DataField="email"HeaderText="邮箱"
SortExpression="email"/>
<asp:BoundField DataField="workdate"HeaderText="工作时间"
SortExpression="workdate"/>
</Columns>
</asp:GridView>
</form>
示例运行结果如图10-25所示。
图 10-25 示例运行结果
10.3.5 CustomExpression
如果上面的表达式类都不能够满足要求,那么可以通过CustomExpression类来提供可用于QueryExtender控件中的自定义LINQ表达式。CustomExpression类使你能够在应用程序中指定自定义表达式,然后在事件处理程序中调用它。
下面的示例演示了如何创建一个由QueryExtender控件使用的CustomExpression对象。其中,该自定义表达式调用包含自定义LINQ表达式的QueryEmployees方法。筛选操作的结果显示在GridView控件中,如代码清单10-7所示。
代码清单10-7 CustomExpressionTest.aspx
<form id="form1"runat="server">
<asp:LinqDataSource ID="LinqDataSource1"
TableName="Employees"runat="server"
ContextTypeName="_10_2.EmployeesDataContext"
EntityTypeName=""Select="new(employeeid, employeename,
department, address, email, workdate)">
</asp:LinqDataSource>
<asp:QueryExtender ID="QueryExtender1"runat="server"
TargetControlID="LinqDataSource1">
<asp:CustomExpression OnQuerying="QueryEmployees">
</asp:CustomExpression>
</asp:QueryExtender>
<asp:GridView ID="GridView1"runat="server"Width="100%"
DataSourceID="LinqDataSource1"
AllowPaging="True"AutoGenerateColumns="False"
DataKeyNames="employeeid">
<Columns>
<asp:BoundField DataField="employeeid"HeaderText="编号"
ReadOnly="True"SortExpression="employeeid"/>
<asp:BoundField DataField="employeename"HeaderText="姓名"
SortExpression="employeename"/>
<asp:BoundField DataField="department"HeaderText="部门"
SortExpression="department"/>
<asp:BoundField DataField="address"HeaderText="住址"
SortExpression="address"/>
<asp:BoundField DataField="email"HeaderText="邮箱"
SortExpression="email"/>
<asp:BoundField DataField="workdate"HeaderText="工作时间"
SortExpression="workdate"/>
</Columns>
</asp:GridView>
</form>
在上面的代码中,通过CustomExpression对象的OnQuerying属性指定了自定义LINQ表达式的QueryEmployees方法。其中,后台的自定义LINQ查询的事件处理程序QueryEmployees代码如下所示:
protected void QueryEmployees(object sender,
CustomExpressionEventArgs e)
{
e.Query=frompin e.Query.Cast<Employee>()
where p.employeeid>=5
select p;
}
示例运行结果如图10-26所示。
图 10-26 示例运行结果