Classificar dados com controles de fonte de dados

Você pode exibir dados em uma página Web ASP.NET utilizando um controle da fonte de dados e um controle associado a dados.Alguns controles de dados permitem aos usuários classificar os dados sem requerer nenhum código.

Se você deseja permitir aos usuários classificar dados no tempo de execução você pode utilizar um controle LinqDataSource, ObjectDataSource, SqlDataSource, ou AccessDataSource como controle da fonte de dados.Para exibir dados que os usuários possam classificar, você pode utilizar tanto um controle GridView como ListView.

Provendo uma Interface do Usuário para Classificação

Você pode criar qualquer interface do usuário (IU) para classificação.De qualquer forma, os controlesGridView e ListView fornecem um IU padrão para classificação.

O controle GridView oferece suporte para classificação em uma única coluna sem qualquer programação.Você coloca a propriedade AllowSorting em true para criar automaticamente o cabeçalho do texto para cada coluna como um link que envia uma expressão classificada para o controle da fonte de dados.Você pode ainda personalizar a funcionalidade da classificação do controle GridView manipulando o evento classificar.Para obter mais informações, consulte Ordenando dados em um controle de servidor Web GridView.

você pode classificar os dados que são exibidos em um controle ListView adicionando um botão ao modelo do controle LayoutTemplate e definindo a propriedade do botão CommandName como "Classificar".Você define a propriedade CommandArgument do botão como o nome da coluna que você deseja utilizar para classificar.Clicando no botão Classificar você alterna a direção de classificação entre Ascending e Descending.Para obter mais informações, consulte Visão Geral sobre o Controle do Servidor Web ListView e Passo-a-passo: Exibindo, paginando e classificando dados usando o controle do servidor Web ListView.

Ativando Classificação em um Controle da Fonte de Dados

Os controles da fonte de dados que oferecem suporte embutido para classificação são os controles LinqDataSource, ObjectDataSource, SqlDataSource, e AccessDataSource.O controle LinqDataSource suporta classificação quando a propriedade AutoSort está definida como true (o padrão), como no exemplo seguinte:

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

O controle SqlDataSource e AccessDataSource suporta classificação apenas quando sua propriedade DataSourceMode está definida como DataSet (o padrão), como no exemplo seguinte:

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

O controle ObjectDataSource suporta classificação se o objeto retornado pelo SelectMethod é um objeto DataSet, DataTable ou DataView.O ObjectDataSource também suporta receber resultados em ordem classificada da fonte de dados.

Ordenação personalizada

Você pode personalizar como a classificação é feita pelos controles associados a dados e os controle da fonte de dados.Isso te habilita a modificar como a classificação automática é executada ou criar uma rotina de classificação personalizada.

Quando você usa o controle LinqDataSource, você pode personalizar a classificação definindo a propriedade AutoSort como false.Você pode criar um manipulador para o evento Selecting.

Quando você usa os controles ObjectDataSource ou SqlDataSource, você pode tirar vantagens da capacidade de classificação utilizando a propriedade SortParameterName.você pode definir a propriedade SortParameterName como o nome do parâmetro que contém uma expressão classificada que esta sendo passado para o controle da fonte de dados.A expressão de classificação é uma lista, delimitada por vírgulas, de campos para serem usados para classificar (e opcionalmente o identificador DESC para classificar em ordem decrescente).Para detalhes sobre o formato de uma expressão de classificação, veja a propriedade DataView.Sort.

O parâmetro identificado pela propriedade SortParameterName é passado ao SelectMethod do controle ObjectDataSource ou passado como parte de uma coleção de parâmetros ao SelectCommand do controle SqlDataSource.O controle ObjectDataSource pode utilizar a informação passado à ele no parâmetro de classificação para retornar dados em ordem classificada.Para o controle SqlDataSource, você deve preencher o nome de um procedimento armazenado que pode pegar o parâmetro de classificação e retornar os dados classificados, porque você não pode passar um parâmetro como parte de uma cláusula ORDER BY.

O seguinte exemplo de código mostra uma declaração de controle ObjectDataSource que identificar um parâmetro nomeado sortColumns como o nome do parâmetro de classificação:

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

O exemplo de código seguinte mostra um método no objeto fonte para o controle ObjectDataSource.O método é identificado como SelectMethod.O parâmetro identificado pela propriedade SortParameterName é usado para classificar os dados recebidos pelo banco de dados.

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;
    }
  }
}

Para obter mais informações, consulte Criando um objeto de origem de controle ObjectDataSource.

Consulte também

Outros recursos

Controles Servidores da Web com fonte de dados