共用方式為


排序含有資料來源控制項的資料

更新:2007 年 11 月

您可以使用資料來源控制項與資料繫結控制項來顯示 ASP.NET Web 網頁中的資料。某些資料控制項可讓使用者直接排序資料,而不需透過任何程式碼來進行。

如果您要讓使用者在執行階段排序資料,則可以使用 LinqDataSourceObjectDataSourceSqlDataSourceAccessDataSource 控制項做為資料來源控制項。若要顯示使用者可以排序的資料,您可以使用 GridView 控制項或 ListView 控制項。

提供使用者介面以進行排序

您可以建立任何使用者介面 (UI) 以進行排序。不過,GridViewListView 控制項都提供了預設的 UI 排序。

您不需設計程式,就能以 GridView 控制項排序單一資料行。若將 AllowSorting 屬性設定為 true,會自動為每個資料行建立標頭文字,做為將排序運算式傳遞至資料來源控制項的連結按鈕。您可以藉由處理排序事件,進一步自訂 GridView 控制項的排序功能。如需詳細資訊,請參閱在 GridView Web 伺服器控制項中排序資料

您可以將按鈕加入至控制項的 LayoutTemplate 範本並將按鈕的 CommandName 屬性設定為 "Sort",藉此排序 ListView 控制項中顯示的資料。您可以將按鈕的 CommandArgument 屬性設定為要做為排序依據的資料行名稱。按一下 [排序] 按鈕,可在 AscendingDescending 這兩個排序方向之間切換。如需詳細資訊,請參閱ListView Web 伺服器控制項概觀逐步解說:使用 ListView Web 伺服器控制項顯示、分頁和排序資料

啟用資料來源控制項中的排序

提供用於排序之內建支援的資料來源控制項為 LinqDataSourceObjectDataSourceSqlDataSourceAccessDataSource 控制項。當 AutoSort 屬性設定為 true (預設值) 時,LinqDataSource 控制項支援排序,如下列範例所示:

<asp:LinqDataSource 
    ContextTypeName="ExampleDataContext" 
    TableName="Products" 
    AutoPage="true"
    AutoSort="true"
    ID="LinqDataSource1" 
    >
</asp:LinqDataSource>
<asp:GridView 
    AllowPaging="true"
    AllowSorting="true"
    DataSourceID="LinqDataSource1"
    ID="GridView1" 
    >
</asp:GridView>
<asp:LinqDataSource 
    ContextTypeName="ExampleDataContext" 
    TableName="Products" 
    AutoPage="true"
    AutoSort="true"
    ID="LinqDataSource1" 
    >
</asp:LinqDataSource>
<asp:GridView 
    AllowPaging="true"
    AllowSorting="true"
    DataSourceID="LinqDataSource1"
    ID="GridView1" 
    >
</asp:GridView>

只有在 DataSourceMode 屬性設定為 DataSet (預設值) 時,SqlDataSourceAccessDataSource 控制項才支援排序,如同下列範例所示:

<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 傳回的物件是 DataSetDataTableDataView 物件,ObjectDataSource 控制項就支援排序。ObjectDataSource 也支援以排序順序從資料來源擷取結果。

自訂排序

您可以自訂資料繫結控制項和資料來源控制項執行排序的方式。這樣一來,您就可以修改自動排序的執行方式,或是建立自訂的排序常式。

當您使用 LinqDataSource 控制項時,可以將 AutoSort 屬性設定為 false 以自訂排序。之後您可以建立 Selecting 事件的處理常式。

當您使用 ObjectDataSourceSqlDataSource 控制項時,可以透過 SortParameterName 屬性利用排序功能。您可以將 SortParameterName 屬性設定為參數名稱,參數中包含傳遞給資料來源控制項的排序運算式。排序運算式是以逗號分隔的排序依據欄位清單 (以及選擇性的 DESC,以遞減順序排序的識別項)。如需排序運算式格式的詳細資訊,請參閱 DataView.Sort 屬性。

SortParameterName 屬性識別的參數會傳遞給 ObjectDataSource 控制項的 SelectMethod,或做為參數集合的一部分傳遞給 SqlDataSource 控制項的 SelectCommandObjectDataSource 控制項可以在排序參數中使用傳遞給它的資訊,以便使用已排序順序的方式傳回資料。針對 SqlDataSource 控制項,因為您無法將參數做為 ORDER BY 子句的一部分傳遞,所以您必須提供能夠取得排序參數,然後傳回排序資料的預存程序名稱。

下列程式碼範例,示範了將名為 sortColumns 的參數識別為排序參數名稱的 ObjectDataSource 控制項宣告:

<asp:ObjectDataSource 
  ID="EmployeesObjectDataSource" 
   
  TypeName="Samples.AspNet.Controls.NorthwindEmployee" 
  SortParameterName="SortColumns"
  EnablePaging="true"
  StartRowIndexParameterName="StartRecord"
  MaximumRowsParameterName="MaxRecords" 
  SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>
<asp:ObjectDataSource 
  ID="EmployeesObjectDataSource" 
   
  TypeName="Samples.AspNet.Controls.NorthwindEmployee" 
  SortParameterName="SortColumns"
  EnablePaging="true"
  StartRowIndexParameterName="StartRecord"
  MaximumRowsParameterName="MaxRecords" 
  SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

下列程式碼範例,示範了 ObjectDataSource 控制項來源物件中的方法。方法會識別為 SelectMethodSortParameterName 屬性識別的參數,會用來排序從資料庫擷取的資料。

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 控制項來源物件

請參閱

其他資源

資料來源 Web 伺服器控制項