使用数据源控件对数据进行排序
更新:2007 年 11 月
通过使用数据源控件和数据绑定控件,可以在 ASP.NET 网页中显示数据。有些数据控件还允许用户对数据进行排序,而不用编写任何代码。
如果要使用户能够在运行时对数据排序,可以使用 LinqDataSource、ObjectDataSource、SqlDataSource 或 AccessDataSource 控件作为数据源控件。若要显示可由用户排序的数据,可以使用 GridView 控件或 ListView 控件。
提供用于排序的用户界面
您可以创建任何用于排序的用户界面 (UI)。但是,GridView 和 ListView 控件提供了默认的用户界面排序。
GridView 控件支持在不需要任何编程的情况下通过单个列排序。通过将 AllowSorting 属性设置为 true,可自动将每个列的标题文本创建为向数据源控件传递排序表达式的链接按钮。而通过处理排序事件,还可以进一步自定义 GridView 控件的排序功能。有关更多信息,请参见对 GridView Web 服务器控件中的数据进行排序。
通过在 ListView 控件的 LayoutTemplate 模板中添加一个按钮,并将该按钮的 CommandName 属性设置为“Sort”,可以对该控件中显示的数据排序。该按钮的 CommandArgument 属性应设置为要用作排序依据的列名。单击“Sort”(排序)按钮可在排序方向 Ascending 和 Descending 之间切换。有关更多信息,请参见 ListView Web 服务器控件概述和演练:使用 ListView Web 服务器控件对数据进行显示、分页和排序。
在数据源控件中启用排序
对排序提供内置支持的数据源控件是 LinqDataSource、ObjectDataSource、SqlDataSource 和 AccessDataSource 控件。在将 AutoSort 属性设置为 true(默认值)时,LinqDataSource 控件会支持排序,如下面的示例所示:
<asp:LinqDataSource
ContextTypeName="ExampleDataContext"
TableName="Products"
AutoPage="true"
AutoSort="true"
ID="LinqDataSource1"
runat="server">
</asp:LinqDataSource>
<asp:GridView
AllowPaging="true"
AllowSorting="true"
DataSourceID="LinqDataSource1"
ID="GridView1"
runat="server">
</asp:GridView>
<asp:LinqDataSource
ContextTypeName="ExampleDataContext"
TableName="Products"
AutoPage="true"
AutoSort="true"
ID="LinqDataSource1"
runat="server">
</asp:LinqDataSource>
<asp:GridView
AllowPaging="true"
AllowSorting="true"
DataSourceID="LinqDataSource1"
ID="GridView1"
runat="server">
</asp:GridView>
SqlDataSource 和 AccessDataSource 控件只有在其 DataSourceMode 属性设置为 DataSet(默认)时才支持排序,如下面的示例所示:
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
DataKeyNames="EmployeeID"
AllowSorting="True"
RunAt="Server" />
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnectionString %>"
RunAt="server" />
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
DataKeyNames="EmployeeID"
AllowSorting="True"
RunAt="Server" />
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnectionString %>"
RunAt="server" />
如果 SelectMethod 返回的对象是 DataSet、DataTable 或 DataView 对象,则 ObjectDataSource 控件支持排序。ObjectDataSource 还支持按排序后的顺序对数据源中的结果进行检索。
自定义排序
您可以自定义数据绑定控件和数据源控件执行排序的方式。这样,将可以修改自动排序的执行方式,也可以创建自定义排序例程。
使用 LinqDataSource 控件时,可通过将 AutoSort 属性设置为 false 自定义排序。随后可以为 Selecting 事件创建处理程序。
使用 ObjectDataSource 或 SqlDataSource 控件时,可通过 SortParameterName 属性来利用各种排序功能。可以将 SortParameterName 属性设置为包含传递到数据源控件的排序表达式的参数名称。排序表达式是作为排序依据的字段的列表,这些字段间以逗号分隔(还可以选择 DESC 标识符按降序排列)。有关排序表达式格式的详细信息,请参见 DataView.Sort 属性。
由 SortParameterName 属性标识的参数被传递给 ObjectDataSource 控件的 SelectMethod 或作为参数集合的一部分传递给 SqlDataSource 控件的 SelectCommand。ObjectDataSource 控件可以使用在排序参数中传递给它的信息,从而按排序后的顺序返回数据。对于 SqlDataSource 控件,由于不能将参数作为 ORDER BY 子句的一部分进行传递,因此必须提供可获取排序参数并返回已排序数据的存储过程的名称。
下面的代码示例演示一个 ObjectDataSource 控件声明,它将一个名为 sortColumns 的参数标识为排序参数名称:
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>
下面的代码示例演示 ObjectDataSource 控件源对象中的一个方法。该方法被标识为 SelectMethod。由 SortParameterName 属性标识的参数用于对从数据库中检索的数据进行排序。
Public Shared Sub Initialize()
' Initialize data source. Use "Northwind" connection string from configuration.
If ConfigurationManager.ConnectionStrings("Northwind") Is Nothing OrElse _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString.Trim() = "" Then
Throw New Exception("A connection string named 'Northwind' with a valid connection string " & _
"must exist in the <connectionStrings> configuration section for the application.")
End If
_connectionString = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
_initialized = True
End Sub
' Select all employees.
<DataObjectMethod(DataObjectMethodType.Select, True)> _
Public Shared Function GetAllEmployees(sortColumns As String, startRecord As Integer, maxRecords As Integer) As DataTable
VerifySortColumns(sortColumns)
If Not _initialized Then Initialize()
Dim sqlCommand As String = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode FROM Employees "
If sortColumns.Trim() = "" Then
sqlCommand &= "ORDER BY EmployeeID"
Else
sqlCommand &= "ORDER BY " & sortColumns
End If
Dim conn As SqlConnection = New SqlConnection(_connectionString)
Dim da As SqlDataAdapter = New SqlDataAdapter(sqlCommand, conn)
Dim ds As DataSet = New DataSet()
Try
conn.Open()
da.Fill(ds, startRecord, maxRecords, "Employees")
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try
If ds.Tables("Employees") IsNot Nothing Then _
Return ds.Tables("Employees")
Return Nothing
End Function
'''''
' Verify that only valid columns are specified in the sort expression to aSub a SQL Injection attack.
Private Shared Sub VerifySortColumns(sortColumns As String)
If sortColumns.ToLowerInvariant().EndsWith(" desc") Then _
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5)
Dim columnNames() As String = sortColumns.Split(",")
For Each columnName As String In columnNames
Select Case columnName.Trim().ToLowerInvariant()
Case "employeeid"
Case "lastname"
Case "firstname"
Case ""
Case Else
Throw New ArgumentException("SortColumns contains an invalid column name.")
End Select
Next
End Sub
public static void Initialize()
{
// Initialize data source. Use "Northwind" connection string from configuration.
if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "")
{
throw new Exception("A connection string named 'Northwind' with a valid connection string " +
"must exist in the <connectionStrings> configuration section for the application.");
}
_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
_initialized = true;
}
// Select all employees.
[DataObjectMethod(DataObjectMethodType.Select, true)]
public static DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords)
{
VerifySortColumns(sortColumns);
if (!_initialized) { Initialize(); }
string sqlCommand = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode FROM Employees ";
if (sortColumns.Trim() == "")
sqlCommand += "ORDER BY EmployeeID";
else
sqlCommand += "ORDER BY " + sortColumns;
SqlConnection conn = new SqlConnection(_connectionString);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand, conn);
DataSet ds = new DataSet();
try
{
conn.Open();
da.Fill(ds, startRecord, maxRecords, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];
return null;
}
//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL Injection attack.
private static void VerifySortColumns(string sortColumns)
{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);
string[] columnNames = sortColumns.Split(',');
foreach (string columnName in columnNames)
{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}
有关更多信息,请参见创建 ObjectDataSource 控件源对象。