データ ソース コントロールによるデータの並べ替え

更新 : 2007 年 11 月

データ ソース コントロールとデータ バインド コントロールを使用すると、ASP.NET Web ページでデータを表示できます。一部のデータ コントロールでは、コードを使用しなくてもデータを並べ替えることができます。

実行時にユーザーがデータを並べ替えられるようにするには、LinqDataSourceObjectDataSourceSqlDataSourceAccessDataSource のいずれかのコントロールをデータ ソース コントロールとして使用します。ユーザーが並べ替えられるデータを表示するには、GridView コントロールまたは ListView コントロールを使用します。

並べ替え用ユーザー インターフェイスの提供

並べ替え用に任意のユーザー インターフェイス (UI: User Interface) を作成できます。ただし、GridView コントロールと ListView コントロールには、既定の UI 並べ替え機能が用意されています。

GridView コントロールは、単一列での並べ替えをサポートします。この場合、プログラミングは必要ありません。AllowSorting プロパティを true に設定すると、各列のヘッダー テキストが自動的にリンク ボタンとして作成されます。このボタンは、並べ替え式をデータ ソース コントロールに渡します。並べ替えイベントを処理することにより、GridView コントロールの並べ替え機能をさらにカスタマイズできます。詳細については、「GridView Web サーバー コントロールでのデータの並べ替え」を参照してください。

コントロールの LayoutTemplate テンプレートにボタンを追加し、ボタンの CommandName プロパティを "Sort" に設定することで、ListView コントロールに表示されるデータを並べ替えることができます。ボタンの CommandArgument プロパティを、並べ替えの基準にする列名に設定します。Sort ボタンをクリックすると、並べ替えの方向が AscendingDescending の間で切り替わります。詳細については、「ListView Web サーバー コントロールの概要」および「チュートリアル : ListView Web サーバー コントロールを使用したデータの表示、ページング、および並べ替え」を参照してください。

データ ソース コントロールの並べ替え機能の有効化

並べ替えのための組み込みサポートが用意されているデータ ソース コントロールは、LinqDataSourceObjectDataSourceSqlDataSource、および AccessDataSource の各コントロールです。LinqDataSource コントロールは、次の例のように AutoSort プロパティが true (既定値) に設定されている場合に並べ替え機能をサポートします。

<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" />

ObjectDataSource コントロールは、SelectMethod が返すオブジェクトが DataSetDataTable、または DataView の各オブジェクトの場合に並べ替え機能をサポートします。ObjectDataSource では、データ ソースで並べ替えられた順序で結果を取得できます。

カスタムの並べ替え

データ バインド コントロールとデータ ソース コントロールによる並べ替えの実行方法をカスタマイズできます。これにより、自動並べ替えの実行方法を変更したり、カスタム並べ替えルーチンを作成したりできます。

LinqDataSource コントロールを使用する場合は、AutoSort プロパティを false に設定することで並べ替え機能をカスタマイズできます。次に、Selecting イベントのハンドラを作成します。

ObjectDataSource コントロールまたは SqlDataSource コントロールを使用する場合は、SortParameterName プロパティを使用して並べ替え機能を利用できます。SortParameterName プロパティは、データ ソース コントロールに渡す並べ替え式を含むパラメータの名前に設定できます。並べ替え式は、並べ替えに使用するフィールドをコンマで区切ったリストで、降順で並べ替える場合は、DESC 識別子も指定できます。並べ替え式の形式の詳細については、DataView.Sort プロパティを参照してください。

SortParameterName プロパティによって指定されたパラメータは、ObjectDataSource コントロールの SelectMethod に渡されるか、またはパラメータ コレクションの一部として SqlDataSource コントロールの SelectCommand に渡されます。ObjectDataSource コントロールは、並べ替えパラメータによって渡された情報を使用して、並べ替えられた順序でデータを返すことができます。SqlDataSource コントロールの場合は、ORDER BY 句の一部としてパラメータを渡すことができないため、並べ替えパラメータを受け取って並べ替えられたデータを返すストアド プロシージャの名前を指定する必要があります。

並べ替えパラメータの名前として sortColumns というパラメータを指定する ObjectDataSource コントロールの宣言のコード例を次に示します。

<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 コントロールのソース オブジェクト」を参照してください。

参照

その他の技術情報

データ ソース Web サーバー コントロール