Quando exibimos ao cliente uma grande quantidade de dados, algumas funcionalidades se fazem essenciais para que ele possa visualizar e analisar estes dados de forma mais eficiente. Uma dessas funcionalidades é chamada de ordenação de colunas, ou Sorting.
Quando utilizamos o DataGrid da versão 1.x do ASP.NET, para poder ter esta funcionalidade, tínhamos que, através do evento SortCommand do DataGrid, recuperar a coluna que foi clicada pelo usuário e invocar novamente o procedimento que resgata os dados e popula o Datagrid, informando a coluna que será utilizada para efetuar a ordenação. Agora, com o controle GridView, conseguimos obter esta funcionalidade sem a escrita de nenhuma linha de código, salvo quando utilizamos o objeto ObjectDataSource.
Utilizando o objeto SqlDataSouce
Para habilitarmos esta funcionalidade no controle GridView utilizando o objeto SqlDataSource devemos clicar na Smart Tag e marcar o CheckBox chamado Enable Sorting, como é mostrado na imagem abaixo:
|
Figura 1 – Habilitando a Ordernação de Registros. |
Habilitando esta opção, o controle GridView já fará a ordenação dos registros automaticamente. Através do código HTML abaixo da página ASPX, vemos como o mesmo ficou configurado:
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="False" AllowSorting="True" DataKeyNames="UsuarioID"> <Columns> <asp:BoundField DataField="Nome" HeaderText="Nome" SortExpression="Nome" /> <asp:BoundField DataField="Email" HeaderText="Email" /> </Columns> </asp:GridView> |
Analisando o código acima podemos notar a propriedade SortExpression da coluna do tipo BoundField. É através desta propriedade que o ASP.NET se encarrega de ordenar a coluna automaticamente clicada pelo usuário e, no caso acima, somente a ordenação para a coluna Nome está habilitada. Algo importante à dizer é que a propriedade SortExpression deve conter exatamente o nome da coluna da fonte de dados para que a ordernação seja possível.
O objeto SqlDataSource possui um propriedade chamada DataSourceMode. Através desta propriedade você define ao objeto SqlDataSource qual será a forma, Dataset ou DataReader, que ele utilizará para resgatar os dados da base de dados. Por padrão, ou seja, quando não definimos esta propriedade, o SqlDataSource faz isso utilizando um objeto do tipo Dataset.
como já vimos acima, essa ordenação é feita automaticamente somente quando definimos a propriedade DataSourceMode como Dataset (ou quando omitimos). Quando definimos esta propriedade como DataReader, sem mais nenhuma outra configuração no objeto SqlDataSource, receberemos a seguinte exceção:
|
Figura 2 – Exceção causada utilizando a propriedade DataSourceMode incorretamente. |
Quando definimos o objeto DataReader para recuperar os dados e quisermos também ter a ordenação dos registros, devemos fazer alguns outros ajustes no objeto SqlDataSource para alcançar este objetivo. Vamos analisá-los passo à passo abaixo:
-
A propriedade DataSourceMode: Definimos para DataReader quando queremos utilizar este para recuperar os dados da fonte de dados.
-
A propriedade SelectCommand: Por design, somente conseguimos isso utilizando uma Stored Procedure. É nesta propriedade que devemos definir o nome da Stored Procedure que será responsável por recuperar os dados.
-
A propriedade SelectCommandType: Como a propriedade SelectCommand estará armazenando uma Stored Procedure, através da SelectCommandType informaremos exatamente isso, ou seja, informar ao ASP.NET que é uma Stored Procedure ao invés de um Sql Statement.
-
A propriedade SortParameterName: É justamente o parâmetro que estará dentro da Stored Procedure e que será responsável pela ordenação. Automaticamente o ASP.NET associa o nome da coluna clicada pelo usuário (a propriedade SortExpression) como o value deste parâmetro. Nota: Não há necessidade de colocar o “@” no nome deste parâmetro.
Para exemplificar o uso do objeto DataReader para recuperar os dados através do SqlDataSource e utilizar a ordenação dos dados, abaixo é exibido o código HTML da página ASPX e a respectiva Stored Procedure (que está definida na propriedade SelectCommand):
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnString %>" DataSourceMode="DataReader" SortParameterName="Coluna" SelectCommand="Sorting" SelectCommandType="StoredProcedure"> </asp:SqlDataSource> <asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="False" AllowSorting="True" DataKeyNames="UsuarioID"> <Columns> <asp:BoundField DataField="Nome" HeaderText="Nome" SortExpression="Nome" /> </Columns> </asp:GridView> |
ALTER PROCEDURE dbo.Sorting @Coluna As Varchar(30) AS DECLARE @Query As NVarchar(4000) SET @Query = 'SELECT Nome, Email, UsuarioID FROM Usuario' IF @Coluna != '' SET @Query = @Query + ' ORDER BY ' + @Coluna EXECUTE sp_executesql @Query |
Como vemos, a Stored Procedure recebe um parâmetro que será utilizado para efetuar a ordenação. Reparem que o nome do parâmetro da Stored Procedure é o mesmo que está definido na propriedade SortParameterName do objeto SqlDataSource. A verificação do valor deste parâmetro, se é ou não vazio, é necessária pois a primeira vez que a página for carregada não é passado nenhum valor à ele.
Utilizando o objeto ObjectDataSouce
Ao contrário do objeto SqlDataSouce, o objeto ObjectDataSouce necessita de algum código adicional justamente porque o mesmo está ligado à uma classe de regras negócios, a qual deve contemplar a ordenação de um result-set qualquer. O processo de ordenação para o objeto ObjectDataSource é basicamente idêntico ao mostrado acima com o objeto SqlDataSource, apenas contemplando nos parâmetros do método que retorna a coleção de objetos uma string que representará a coluna à ser ordenada.
Como a parte de vinculação do objeto ObjectDataSouce ao controle GridView é semelhante à forma acima, vamos diretamente analisar o código que será responsável pela ordenação de registros:
using System; using System.Data; using System.Data.SqlClient; using System.Configuration; using System.Web.Configuration; using System.Collections.Generic; public class Usuarios { public List<Usuario> ResgataUsuarios() { return ResgataUsuarios(string.Empty); } public List<Usuario> ResgataUsuarios(string coluna) { List<Usuario> coll = new List<Usuario>(); string connString = WebConfigurationManager.ConnectionStrings["ConnString"].ConnectionString SqlConnection conn = new SqlConnection(connString); string query = "SELECT UsuarioID, Nome, Email FROM Usuario"; if(coluna != string.Empty) query += " ORDER BY " + coluna; SqlCommand cmd = new SqlCommand(query, conn); SqlDataReader dr = null; try { conn.Open(); dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); while(dr.Read()){ Usuario u = new Usuario(); u.ID = dr.GetInt32(0); u.Nome = dr.GetString(1); u.Email = dr.GetString(2); coll.Add(u); } } finally { if (dr != null) dr.Close(); } return coll; } } |
Analisando o código acima temos sobrecarga para o método ResgataUsuarios, onde em um deles recebemos uma string que corresponde à coluna a ser ordenada. Como fizemos com a Stored Procedure, neste método também analisamos se o parâmetro é ou não vazio pois, a partir disto, acrescentamos a cláusula ORDER BY, se necessário. Há ainda pequenas configurações a serem feitas no objeto ObjectDataSource, ou seja, no caso deste objeto, em sua Smart Tag, não temos o CheckBox para habilitar a Ordenação, tendo assim que recorrer à janela de propriedade e marcar a propriedade AllowSorting como True.
Além disso precisamos também definir a propriedade SortParameterName onde, neste caso, irá o nome do parâmetro responsável pela ordenação do nosso método ResgataUsuarios, que é coluna. Vejamos abaixo o código HTML resultante na página ASPX depois dessas configurações:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="ResgataUsuarios" SortParameterName="coluna" TypeName="Usuarios"> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1" AllowSorting="True"> <Columns> <asp:BoundField DataField="Nome" HeaderText="Nome" SortExpression="Nome" /> </Columns> </asp:GridView> |
Automaticamente em runtime, o ASP.NET define o valor da propriedade SortExpression clicada pelo usuário como value do parâmetro do método ResgataUsuarios. Essa atribuição é possível pois já temos mapeado na propriedade SortParameterName o nome do parâmetro responsável pela ordenação do método referido.
Observação Importante: A propriedade SortParameterName é extremamente importante, independentemente de qual objeto de Data Source utilizamos no controle GridView: isso porque podemos ter vários parâmetros na Stored Procedure ou mesmo no método da classe de negócios.