Como não poderia ser diferente, o controle GridView também permite a edição de registros “in-place”, ou seja, no mesmo local que exibimos estes registros podemos editá-los e gravar este novo valor na base de dados (ou qualquer outro repositório) e o mais interessante: sem escrever nenhuma linha de código, ao contrário do controle DataGrid do ASP.NET 1.x.
A facilidade que este controle fornece para criarmos a edição de registros é bastante simples pois, além dos Wizards, temos ainda as Smart Tags que habilitam ao desenvolvedor, através de poucos cliques, deixar isso em funcionamento. Veremos abaixo a forma de como habilitar a edição de registros “in-place” utilizando os objetos SqlDataSource e o ObjectDataSource.
Utilizando o objeto SqlDataSource
Primeiramente devemos definir o objeto SqlDataSource, que será o intermediário entre o controle GridView e a fonte de dados SQL Server. É através dele que vamos configurar as colunas à serem exibidas e editadas no controle GridView. Como já vimos isso nos capítulos anteriores, vamos pular esta parte, mas apenas chamo a atenção para o momento que definir as colunas onde, haverá um botão chamado Advanced… , o qual deveremos clicar. Com isso uma janela será exibida e devemos marcar a opção “Generate INSERT, UPDATE and DELETE statements” que com isso os comandos de Insert, Update e Delete serão automaticamente gerados baseando-se nas colunas que selecionamos no SelectCommand. A imagem abaixo ilustra este processo:
|
Figura 1 – Definindo os comandos de CRUD. |
Feito isso temos que vincular esta fonte de dados ao controle GridView através da propriedade DataSourceID. Com este vínculo podemos então definir as colunas que desejamos exibir no controle GridView e, além disso, devemos adicionar uma coluna do tipo CommandField ou apenas marcando a opção Enable Editing na Smart Tag. Através das imagens abaixo vemos estes dois processos respectivamente:
|
Figura 2 – Definindo a coluna do tipo CommandField. |
|
Figura 3 – Habilitando a edição de registros através da propriedade Enable Editing da Smart Tag. |
O código HTML gerado com essas configurações na página ASPX está sendo exibido abaixo:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnString %>" SelectCommand="SELECT Email, Nome, UsuarioID FROM Usuario" UpdateCommand="UPDATE Usuario SET Email = @Email, Nome = @Nome WHERE UsuarioID = @original_UsuarioID"> <UpdateParameters> <asp:Parameter Name="Email" Type="String" /> <asp:Parameter Name="Nome" Type="String" /> <asp:Parameter Name="original_UsuarioID" Type="Int32" /> </UpdateParameters> </asp:SqlDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="UsuarioID" DataSourceID="SqlDataSource1"> <Columns> <asp:CommandField ShowEditButton="True" /> <asp:BoundField DataField="UsuarioID" HeaderText="UsuarioID" ReadOnly="True" /> <asp:BoundField DataField="Email" HeaderText="Email" /> <asp:BoundField DataField="Nome" HeaderText="Nome" /> </Columns> </asp:GridView> |
Analisando o código acima vemos o que já descrevemos: a vinculação do objeto de Data Source ao controle GridView. A única propriedade que vemos neste código e que ainda não nos deparamos é a propriedade ReadOnly. Esta é utilizada quando não queremos habilitar um registro que é exibido no controle GridView para edição. Um caso comum é quando temos em nosso GridView o ID ou um código de registro em que não devemos alterá-lo. Ao definí-la para True, a coluna é exibida apenas em forma de Label, mesmo a linha em formato de edição, assim como podemos ver a imagem abaixo:
|
Figura 4 – A edição do controle GridView em funcionamento. |
Observação: A propriedade DataKeyNames, que no caso deste exemplo está definida como UsuarioID, ou seja, é o ID do registro, faz se necessário, pois o ASP.NET utiliza esta propriedade para recuperar o ID do registro corrente que está sendo editado e passa este valor para o parâmetro original_UsuarioID (qual vamos analisá-lo mais adiante, em um artigo posterior) e, conseqüentemente, o comando responsável pela atualização (UpdateCommand) utilizará este valor para persistir as alterações na base de dados.
Utilizando o objeto ObjectDataSource
Como a forma de definirmos as colunas é independente da fonte de dados que estamos utilizando, apenas vamos nos restringir a falar de como configurar os métodos a serem utilizados para este processo, já que o restante é da mesma forma que utilizamos com o objeto SqlDataSource.
Devemos primeiramente criar um método responsável pela atualização dos dados na fonte de dados que, por sua vez, receberá os parâmetros necessários para efetuar tal atualização. No cenário que vamos utilizar, este método receberá três parâmetros: nome, email e ID (identificação do registro como único) e o método se chamará Update. Abaixo é exibido como criar este método na classe de negócios:
public void Update(string nome, string email, int id) { SqlConnection conn = new SqlConnection( WebConfigurationManager.ConnectionStrings["ConnString"].ConnectionString); SqlCommand cmd = new SqlCommand("UPDATE Usuario SET Nome = @Nome, Email = @Email WHERE UsuarioID = @ID", conn); cmd.Parameters.AddWithValue("@Nome", nome); cmd.Parameters.AddWithValue("@Email", email); cmd.Parameters.AddWithValue("@ID", id); try { conn.Open(); cmd.ExecuteNonQuery(); } finally { if (conn != null) { conn.Close(); } } } |
Analisando o código acima vemos que é criado um objeto que é responsável pela conexão com a fonte de dados e outro objeto em qual definimos a query T-SQL a ser executada (neste caso, uma query de Update). Definidos estes objetos, utilizamos o método AddWithValue da coleção de parâmetros do objeto SqlCommand para adicionarmos os parâmetros necessários para executarmos a query de atualização. Finalmente abrimos a conexão com a fonte de dados, invocamos o método ExecuteNonQuery para executar o comando e posteriormente fechamos a conexão com a fonte de dados.
Depois do método codificado corretamente na classe que contém as regras de negócios devemos então, neste momento, configurar o objeto ObjectDataSource onde, na propriedade UpdateMethod, definiremos este método e seus respectivos parâmetros. O código ASPX abaixo mostra este configuração:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="ResgataUsuarios" TypeName="Usuarios" UpdateMethod="Update"> <UpdateParameters> <asp:Parameter Name="nome" Type="String" /> <asp:Parameter Name="email" Type="String" /> </UpdateParameters> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1"> <Columns> <asp:CommandField ShowEditButton="True" /> <asp:BoundField DataField="ID" HeaderText="ID" /> <asp:BoundField DataField="Email" HeaderText="Email" /> <asp:BoundField DataField="Nome" HeaderText="Nome" /> </Columns> </asp:GridView> |
Analisando o código superior vemos todos os parâmetros que definimos na assinatura do método Update configurados na seção UpdateParameters que, automaticamente, o ASP.NET define seus valores e invoca o método Update quando o usuário clicar no botão de atualização.
Muitas vezes o método de atualização não espera tipos de dados simples como vimos acima, ou seja, o mesmo receberá ao invés de strings contendo os valores como por exemplo nome, email, etc., ele receberá um objeto complexo do tipo Usuario, que contém suas propriedades. Neste cenário devemos modificar o código do método de atualização para receber este tipo de objeto e também ajustar a propriedade DataObjectTypeName no controle ObjectDataSource que é onde definimos uma string contendo o tipo de objeto que este controle irá trabalhar. Para exemplificar melhor isso, veremos abaixo o código HTML da página ASPX e o método responsável pela atualização, recebendo em seu parâmetro um tipo complexo:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="ResgataUsuarios" TypeName="Usuarios" DataObjectTypeName="Usuario" UpdateMethod="Update"> </asp:ObjectDataSource> |
public void Update(Usuario u) { SqlConnection conn = new SqlConnection( WebConfigurationManager.ConnectionStrings["ConnString"].ConnectionString); SqlCommand cmd = new SqlCommand("UPDATE Usuario SET Nome = @Nome, Email = @Email WHERE UsuarioID = @ID", conn); cmd.Parameters.AddWithValue("@Nome", u.Nome); cmd.Parameters.AddWithValue("@Email", u.Email); cmd.Parameters.AddWithValue("@ID", u.ID); try { conn.Open(); cmd.ExecuteNonQuery(); } finally { if (conn != null) { conn.Close(); } } } |
É importante dizer que quando utilizamos o objeto complexo, no caso Usuario, deverá obrigatoriamente ter um construtor público sem parâmetros, as propriedades deverão ser estar definidas como públicas e com o mesmo nome que são passadas para o GridView e, as propriedades devem aceitar leitura e escrita (Get e Set).
Boas Maraba,
Certifique-se de que está carregando o GridView dentro da condição If (!this.IsPostBack) { }, no evento Load da página.